Skip to content

Commit f08d88e

Browse files
authored
test: add vfkit functional test to github actions (#21325)
* add vfkit functional test * trigger the test * fix post mortem logs not showing when status is running with warning * revert dot * bump time-out * detect time outs * debug * no bash 0 * detect timeout and exit failure on timeout * refactor the end results to use funcs * dont rename setup-go * more refacor * time elapsed * fix time_elapsed not being set * try capture run exit code * revert unneeded changes * remove time duration dupolicate * remove wait-timeout as extra arg * bump timeout for all jobs to reduce flakes for timeout * remove extrafile
1 parent 770d5ce commit f08d88e

File tree

1 file changed

+138
-55
lines changed

1 file changed

+138
-55
lines changed

.github/workflows/functional_test.yml

Lines changed: 138 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -64,22 +64,20 @@ jobs:
6464
driver: docker
6565
cruntime: docker
6666
os: ubuntu-22.04
67-
# will try to choose lowest time out per environment (+3m avg)
68-
# Test taking longer than their usual's should also be treated as a failure
69-
test-timeout: 10m
67+
test-timeout: 15m
7068
- name: docker-containerd-ubuntu-22.04-x86_64
7169
driver: docker
7270
cruntime: containerd
7371
extra-start-args: --container-runtime=containerd
7472
os: ubuntu-22.04
75-
test-timeout: 10m
73+
test-timeout: 15m
7674
- name: docker-containerd-rootless-ubuntu-22.04-x86_64
7775
driver: docker
7876
cruntime: containerd
7977
os: ubuntu-22.04
8078
extra-start-args: --container-runtime=containerd --rootless
8179
rootless: true
82-
test-timeout: 9m
80+
test-timeout: 15m
8381
- name: podman-docker-ubuntu-24.04-x86_64
8482
driver: podman
8583
cruntime: docker
@@ -95,7 +93,13 @@ jobs:
9593
cruntime: docker
9694
os: macos-13
9795
extra-start-args: --network socket_vmnet
98-
test-timeout: 30m
96+
test-timeout: 50m
97+
- name: vfkit-docker-macos-13-x86_64
98+
driver: vfkit
99+
cruntime: docker
100+
os: macos-13
101+
extra-start-args: --network vmnet-shared
102+
test-timeout: 50m
99103
steps:
100104
- name: Info Block (macOS)
101105
if: runner.os == 'macOS'
@@ -222,7 +226,18 @@ jobs:
222226
go-version: ${{env.GO_VERSION}}
223227
cache: true
224228
- name: Install gopogh
225-
run: go install github.com/medyagh/gopogh/cmd/[email protected]
229+
shell: bash
230+
run: |
231+
GOPOGH_VERSION=v0.29.0
232+
GOOS=$(go env GOOS)
233+
GOARCH=$(go env GOARCH)
234+
URL="https://github.com/medyagh/gopogh/releases/download/${GOPOGH_VERSION}/gopogh-${GOOS}-${GOARCH}"
235+
echo "Downloading ${URL}"
236+
curl -fsSL "${URL}" -o gopogh
237+
sudo install -m 0755 gopogh /usr/local/bin/gopogh
238+
rm gopogh
239+
command -v gopogh
240+
gopogh -version || true
226241
- name: Set up cgroup v2 delegation (rootless)
227242
if: ${{ matrix.rootless }}
228243
run: |
@@ -354,6 +369,15 @@ jobs:
354369
run: |
355370
brew install qemu socket_vmnet
356371
HOMEBREW=$(which brew) && sudo ${HOMEBREW} services start socket_vmnet
372+
- name: Install vfkit and vmnet_helper (macos)
373+
if: matrix.os == 'macos-13' && matrix.driver == 'vfkit'
374+
run: |
375+
brew install vfkit
376+
machine="$(uname -m)"
377+
archive="vmnet-helper-$machine.tar.gz"
378+
curl -LOf "https://github.com/nirs/vmnet-helper/releases/latest/download/$archive"
379+
sudo tar xvf "$archive" -C / opt/vmnet-helper
380+
sudo install -m 0640 /opt/vmnet-helper/share/doc/vmnet-helper/sudoers.d/vmnet-helper /etc/sudoers.d/
357381
- name: Download Test Binaries
358382
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0
359383
with:
@@ -364,8 +388,9 @@ jobs:
364388
sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/
365389
sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld
366390
- name: Run Integration Test
391+
id: run_test
367392
continue-on-error: true
368-
shell: bash {0}
393+
shell: bash
369394
run: |
370395
set -x
371396
mkdir -p report
@@ -380,27 +405,37 @@ jobs:
380405
sec=$((${TIME_ELAPSED}%60))
381406
TIME_ELAPSED="${min} min $sec seconds "
382407
# make variables available for next step
383-
echo "TIME_ELAPSED=${TIME_ELAPSED}" >> $GITHUB_ENV
408+
echo "TIME_ELAPSED=${TIME_ELAPSED}" >> $GITHUB_ENV
384409
- name: Generate Gopogh HTML Report
410+
if: always()
385411
shell: bash
386412
run: |
387-
go tool test2json -t < ./report/testout.txt > ./report/testout.json || true
388-
STAT=$(gopogh -in ./report/testout.json -out_html ./report/testout.html -out_summary ./report/testout_summary.json -name "${{ matrix.name }} ${GITHUB_REF}" -repo "${GITHUB_REPOSITORY}" -details "${GITHUB_SHA}") || true
389-
PassNum=$(echo $STAT | jq '.NumberOfPass')
390-
FailNum=$(echo $STAT | jq '.NumberOfFail')
391-
TestsNum=$(echo $STAT | jq '.NumberOfTests')
392-
if [ "${FailNum}" -eq 0 ]; then
393-
STATUS_ICON="✓"
394-
elif [ "${FailNum}" -gt 1 ]; then
395-
STATUS_ICON="✗"
396-
elif [ "${PassNum}" -eq 0 ]; then
397-
STATUS_ICON="✗"
413+
# Check if the test step failed AND the log contains "timed out"
414+
if [[ "${{ steps.run_test.outcome }}" == "failure" && $(grep -c "timed out" ./report/testout.txt) -gt 0 ]]; then
415+
# If it was a timeout, set your custom message
416+
RESULT_SHORT="⌛⌛⌛ Test Timed out ${TIME_ELAPSED} ⌛⌛⌛"
398417
else
399-
STATUS_ICON="✗"
418+
go tool test2json -t < ./report/testout.txt > ./report/testout.json || true
419+
STAT=$(gopogh -in ./report/testout.json -out_html ./report/testout.html -out_summary ./report/testout_summary.json -name "${{ matrix.name }} ${GITHUB_REF}" -repo "${GITHUB_REPOSITORY}" -details "${GITHUB_SHA}") || true
420+
PassNum=$(echo $STAT | jq '.NumberOfPass')
421+
FailNum=$(echo $STAT | jq '.NumberOfFail')
422+
TestsNum=$(echo $STAT | jq '.NumberOfTests')
423+
424+
if [ "${FailNum}" -eq 0 ]; then
425+
STATUS_ICON="✓"
426+
else
427+
STATUS_ICON="✗"
428+
fi
429+
if [ "${PassNum}" -eq 0 ]; then
430+
STATUS_ICON="✗"
431+
fi
432+
433+
# Result in one sentence
434+
RESULT_SHORT="${STATUS_ICON} Completed with ${FailNum} / ${TestsNum} failures in ${TIME_ELAPSED}"
400435
fi
401-
# Result in in one sentence
402-
RESULT_SHORT="${STATUS_ICON} Completed with ${FailNum} / ${TestsNum} failures in ${TIME_ELAPSED}"
436+
403437
echo "RESULT_SHORT=${RESULT_SHORT}" >> $GITHUB_ENV
438+
echo "TIME_ELAPSED=${TIME_ELAPSED}" >> $GITHUB_ENV
404439
echo 'STAT<<EOF' >> $GITHUB_ENV
405440
echo "${STAT}" >> $GITHUB_ENV
406441
echo 'EOF' >> $GITHUB_ENV
@@ -428,45 +463,93 @@ jobs:
428463
shell: bash
429464
run: |
430465
summary="$GITHUB_STEP_SUMMARY"
431-
ARTIFACT_NAME="functional-${{ matrix.name }}-${{ steps.vars.outputs.PR_OR_MASTER }}-sha-${{ steps.vars.outputs.COMMIT_SHA }}"
432-
ARTIFACT_ID='${{ steps.upload_gopogh.outputs.artifact-id }}'
433-
if [ -n "$ARTIFACT_ID" ]; then
434-
URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts/$ARTIFACT_ID"
435-
echo "Gopogh report artifact ($ARTIFACT_NAME): $URL"
436-
echo "Download Gopogh report: $URL" >> $GITHUB_STEP_SUMMARY
437-
else
438-
echo "Could not determine artifact ID (action version may not expose it). Find artifact named: $ARTIFACT_NAME"
439-
echo "Report artifact name: $ARTIFACT_NAME" >> $GITHUB_STEP_SUMMARY
440-
fi
466+
Print_Gopogh_Artifact_Download_URL() {
467+
ARTIFACT_NAME="functional-${{ matrix.name }}-${{ steps.vars.outputs.PR_OR_MASTER }}-sha-${{ steps.vars.outputs.COMMIT_SHA }}"
468+
ARTIFACT_ID='${{ steps.upload_gopogh.outputs.artifact-id }}'
469+
if [ -n "$ARTIFACT_ID" ]; then
470+
URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts/$ARTIFACT_ID"
471+
echo "Gopogh report artifact ($ARTIFACT_NAME): $URL"
472+
echo "📥 [Download Gopogh Report]($URL)" >> "$summary"
473+
else
474+
echo "Could not determine artifact ID (action version may not expose it). Find artifact named: $ARTIFACT_NAME"
475+
echo "Report artifact name: $ARTIFACT_NAME" | tee -a "$summary"
476+
fi
477+
}
478+
479+
Print_Gopogh_Artifact_Download_URL
441480
echo "-------------------- RESULT SUMMARY --------------------"
442-
echo "$RESULT_SHORT" | tee -a "$summary"
481+
echo "$RESULT_SHORT" | tee -a "$summary"
482+
echo "Time Elapsed: ${TIME_ELAPSED}" | tee -a "$summary"
443483
444484
numFail=$(echo "$STAT" | jq -r '.NumberOfFail // 0')
445485
numPass=$(echo "$STAT" | jq -r '.NumberOfPass // 0')
446486
numSkip=$(echo "$STAT" | jq -r '.NumberOfSkip // 0')
447-
echo "Failed: ${numFail}" | tee -a "$summary"
448-
echo "Passed: ${numPass}" | tee -a "$summary"
449-
echo "Skipped: ${numSkip}" | tee -a "$summary"
450-
451-
if [ "$numFail" -gt 0 ]; then
452-
echo "------------------------ ${numFail} Failed ------------------------" | tee -a "$summary"
453-
echo "$STAT" | jq -r '.FailedTests[]? | " ✗ \(.)"' | tee -a "$summary"
454-
fi
487+
488+
# Print test counts only if they are non-zero
489+
print_test_counts_only() {
490+
if [ -n "${numFail}" ]; then
491+
echo "Failed: ${numFail}" | tee -a "$summary"
492+
fi
493+
if [ -n "${numPass}" ]; then
494+
echo "Passed: ${numPass}" | tee -a "$summary"
495+
fi
496+
if [ -n "${numSkip}" ]; then
497+
echo "Skipped: ${numSkip}" | tee -a "$summary"
498+
fi
499+
}
455500
456-
echo "------------------------${numPass} Passed ------------------------"
457-
if [ "$numPass" -gt 0 ]; then
458-
echo "$STAT" | jq -r '.PassedTests[]? | " ✓ \(.)"'
459-
fi
501+
print_test_counts_only
460502
461-
if [ "$numSkip" -gt 0 ]; then
462-
echo "------------------------${numSkip} Skipped ------------------------" | tee -a "$summary"
463-
echo "$STAT" | jq -r '.SkippedTests[]? | " • \(.)"' | tee -a "$summary"
464-
fi
503+
# Prints lits of test names grouped by result status
504+
print_test_names_by_status() {
505+
local count="$1" header="$2" sym="$3" field="$4" to_summary="$5"
506+
(( count > 0 )) || return 0
507+
local line="------------------------ ${count} ${header} ------------------------"
508+
if [ "$to_summary" = "yes" ]; then
509+
echo "$line" | tee -a "$summary"
510+
jq -r ".${field}[]? | \" ${sym} \(.)\"" <<<"$STAT" | tee -a "$summary"
511+
else
512+
echo "$line"
513+
jq -r ".${field}[]? | \" ${sym} \(.)\"" <<<"$STAT"
514+
fi
515+
}
465516
466-
echo "---------------------------------------------------------"
517+
print_test_names_by_status "${numFail:-0}" "Failed" "✗" "FailedTests" yes
518+
print_test_names_by_status "${numPass:-0}" "Passed" "✓" "PassedTests" no
519+
print_test_names_by_status "${numSkip:-0}" "Skipped" "•" "SkippedTests" yes
467520
echo $summary >> $GITHUB_STEP_SUMMARY
468-
if [ "$numFail" -gt 0 ];then echo "*** $numFail Failed ***";exit 2;fi
469-
if [ "$numPass" -eq 0 ];then echo "*** 0 Passed! ***";exit 2;fi
470-
# Safe Guard for when tests gets skipped and no failures
471-
if [ "$numPass" -lt 45 ];then echo "*** Failed to pass at least 45 ! ***";exit 2;fi
521+
decide_exit_code() {
522+
# Allow overriding minimum expected passes for when some tests pass and others are timed out
523+
local min_pass="${MIN_PASS_THRESHOLD:-45}"
524+
local timeout_pattern="Test Timed out"
525+
526+
echo "---------------------------------------------------------"
527+
528+
# Timeout detection
529+
if echo "$RESULT_SHORT" | grep -iq "$timeout_pattern"; then
530+
echo "*** Detected test timeout ${TIME_ELAPSED} ⌛: '$timeout_pattern' ***"
531+
exit 3
532+
fi
533+
534+
# Any failures
535+
if [ "${numFail:-0}" -gt 0 ]; then
536+
echo "*** ${numFail} test(s) failed ***"
537+
exit 2
538+
fi
539+
540+
# Zero passes (likely setup issue)
541+
if [ "${numPass:-0}" -eq 0 ]; then
542+
echo "*** No tests passed ***"
543+
exit 4
544+
fi
545+
546+
# Insufficient passes safeguard
547+
if [ "${numPass:-0}" -lt "$min_pass" ]; then
548+
echo "*** Only ${numPass} passed (< required ${min_pass}) ***" | tee -a "$summary"
549+
exit 5
550+
fi
551+
552+
echo "Exit criteria satisfied: ${numPass} passed, ${numFail} failed, ${numSkip} skipped."
553+
}
472554
555+
decide_exit_code

0 commit comments

Comments
 (0)