@@ -270,6 +270,7 @@ jobs:
270270 set -eu
271271
272272 docker buildx bake frontend
273+
273274 if [ "${TEST_SUITE}" = "other" ]; then
274275 exit 0
275276 fi
@@ -283,19 +284,64 @@ jobs:
283284 docker buildx bake worker
284285 env :
285286 TEST_SUITE : ${{ matrix.suite }}
286- - name : Run integration tests
287+ - name : Run integration tests (with coverage tracking)
287288 run : |
288289 set -ex
289- if [ -n "${TEST_SUITE}" ] && [ ! "${TEST_SUITE}" = "other" ]; then
290+ mkdir -p coverage
291+
292+ # The frontend covdata files (covmeta/covcounters) are written by the test harness
293+ # (writeFrontendCovdata) on the RUNNER filesystem.
294+ export DALEC_FRONTEND_GOCOVERDIR="${GITHUB_WORKSPACE}/coverage/frontend-${TEST_SUITE}"
295+ rm -rf "${DALEC_FRONTEND_GOCOVERDIR}"
296+ mkdir -p "${DALEC_FRONTEND_GOCOVERDIR}"
297+
298+ run=""
299+ skip=""
300+ if [ -n "${TEST_SUITE}" ] && [ "${TEST_SUITE}" != "other" ]; then
290301 run="-run=${TEST_SUITE}"
291302 fi
292303 if [ -n "${TEST_SKIP}" ]; then
293304 skip="-skip=${TEST_SKIP}"
294305 fi
295- go test -timeout=59m -v -json ${run} ${skip} ./test | go run ./cmd/test2json2gha --slow 120s --logdir /tmp/testlogs
306+
307+ go test -timeout=59m -v -json \
308+ -covermode=atomic -coverpkg=./... \
309+ -coverprofile="coverage/integration-${TEST_SUITE}.out" \
310+ ${run} ${skip} ./test \
311+ | go run ./cmd/test2json2gha --slow 120s --logdir /tmp/testlogs
312+
313+ # Convert frontend covdata -> legacy coverprofile
314+ if ! ls "${DALEC_FRONTEND_GOCOVERDIR}"/covmeta.* >/dev/null 2>&1; then
315+ echo "::group::frontend coverage debug"
316+ echo "DALEC_FRONTEND_GOCOVERDIR=${DALEC_FRONTEND_GOCOVERDIR}"
317+ echo "Contents:"
318+ ls -la "${DALEC_FRONTEND_GOCOVERDIR}" || true
319+ echo "Searching workspace for covmeta/covcounters..."
320+ find "${GITHUB_WORKSPACE}" \( -name 'covmeta.*' -o -name 'covcounters.*' \) 2>/dev/null | head -n 200 || true
321+ echo "::endgroup::"
322+ echo "::error::No frontend coverage covmeta.* found in ${DALEC_FRONTEND_GOCOVERDIR} (frontend coverage not collected)"
323+ exit 1
324+ fi
325+
326+ go tool covdata textfmt \
327+ -i="${DALEC_FRONTEND_GOCOVERDIR}" \
328+ -o="coverage/frontend-${TEST_SUITE}.out"
296329 env :
297330 TEST_SUITE : ${{ matrix.suite }}
298331 TEST_SKIP : ${{ matrix.skip }}
332+
333+
334+ - name : Upload integration coverage profile
335+ if : always()
336+ uses : actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
337+ with :
338+ name : coverage-integration-${{ matrix.suite }}
339+ path : |
340+ coverage/integration-${{ matrix.suite }}.out
341+ coverage/frontend-${{ matrix.suite }}.out
342+ if-no-files-found : ignore
343+ retention-days : 7
344+
299345 - name : Get traces
300346 if : always()
301347 run : |
@@ -354,8 +400,27 @@ jobs:
354400 cache : false
355401 - name : download deps
356402 run : go mod download
357- - name : Run unit tests
358- run : go test -v --test.short --json ./... | go run ./cmd/test2json2gha
403+ - name : Run unit tests (with coverage tracking)
404+ run : |
405+ set -eux
406+ mkdir -p coverage
407+
408+ pkgs="$(go list ./... | grep -v '/test$' | grep -v '/test/' )"
409+ go test -v --test.short --json \
410+ -covermode=atomic \
411+ -coverprofile="coverage/unit.out" \
412+ ${pkgs} \
413+ | go run ./cmd/test2json2gha
414+ - name : Upload unit coverage profile
415+ if : always()
416+ uses : actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
417+ with :
418+ name : coverage-unit
419+ path : coverage/unit.out
420+ if-no-files-found : ignore
421+ retention-days : 7
422+
423+
359424
360425 e2e :
361426 runs-on : ubuntu-22.04
@@ -443,3 +508,82 @@ jobs:
443508 path : ${{ steps.dump-logs.outputs.DOCKERD_LOG_PATH }}
444509 retention-days : 1
445510
511+ coverage-report :
512+ runs-on : ubuntu-22.04
513+ needs :
514+ - unit
515+ - integration
516+
517+ steps :
518+ - name : Harden Runner
519+ uses : step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1
520+ with :
521+ egress-policy : audit
522+
523+ - name : Checkout
524+ uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
525+
526+ - name : Setup Go
527+ uses : actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
528+ with :
529+ go-version : " 1.25"
530+ cache : false
531+
532+ - name : Download deps
533+ run : go mod download
534+
535+ - name : Download unit coverage artifact
536+ uses : actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
537+ with :
538+ name : coverage-unit
539+ path : coverage
540+
541+ - name : Download integration coverage artifacts
542+ uses : actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
543+ with :
544+ path : coverage/_integration
545+
546+ - name : Merge coverage + generate report
547+ run : |
548+ set -eux
549+ go install github.com/wadey/gocovmerge@latest
550+
551+ integration_profiles="$(find coverage/_integration -type f -name 'integration-*.out' | sort | tr '\n' ' ')"
552+ frontend_profiles="$(find coverage/_integration -type f -name 'frontend-*.out' | sort | tr '\n' ' ')"
553+ if [ -z "${integration_profiles}" ]; then
554+ echo "::error::No integration coverage profiles found"
555+ exit 1
556+ fi
557+
558+ if [ -z "${frontend_profiles}" ]; then
559+ echo "::error::No frontend coverage profiles found"
560+ exit 1
561+ fi
562+
563+ if [ ! -f coverage/unit.out ]; then
564+ echo "::error::Unit coverage profile not found (coverage/unit.out)"
565+ exit 1
566+ fi
567+
568+ "$(go env GOPATH)/bin/gocovmerge" coverage/unit.out ${integration_profiles} ${frontend_profiles} > coverage/all.out
569+
570+ go tool cover -func=coverage/all.out | tee coverage/summary.txt
571+ go tool cover -html=coverage/all.out -o coverage/index.html
572+
573+ total="$(tail -n 1 coverage/summary.txt | awk '{print $3}')"
574+ {
575+ echo "## Coverage"
576+ echo
577+ echo "- Total: **${total}**"
578+ echo "- Profiles merged: $(echo "${integration_profiles}" | wc -w) integration + $(echo "${frontend_profiles}" | wc -w) frontend"
579+ } >> "${GITHUB_STEP_SUMMARY}"
580+
581+ - name : Upload merged coverage report
582+ uses : actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
583+ with :
584+ name : coverage-report
585+ path : |
586+ coverage/all.out
587+ coverage/summary.txt
588+ coverage/index.html
589+ retention-days : 14
0 commit comments