@@ -17,6 +17,10 @@ CI_COVERAGE_DIR ?= /tmp/gh-aw-ci-coverage
1717CI_COVERAGE_ENABLED ?= 1
1818CI_COVERAGE_SOURCE_BRANCH ?= main
1919CI_RUN_ID ?=
20+ CI_UNIT_WORKFLOW_FILE ?= cgo.yml
21+ CI_UNIT_TEST_ARTIFACT_PATTERN ?= test-result-cgo-unit
22+ CI_UNIT_RUN_ID ?=
23+ GO_IMPACTED_TEST_MAX_SECONDS ?= 60
2024
2125# Build flags
2226LDFLAGS =-ldflags "-s -w -X main.version=$(VERSION ) "
@@ -256,13 +260,13 @@ test-impacted-go:
256260 echo " No changed Go files; skipping impacted Go tests." ; \
257261 exit 0; \
258262 fi ; \
263+ COVERAGE_SOURCE_BRANCH=" $( CI_COVERAGE_SOURCE_BRANCH) " ; \
259264 COVERAGE_GO_PACKAGES=" " ; \
260265 if [ " $( CI_COVERAGE_ENABLED) " != " 1" ]; then \
261266 echo " CI coverage correlation disabled (CI_COVERAGE_ENABLED=$( CI_COVERAGE_ENABLED) ); using changed-file package selection." ; \
262267 elif ! command -v gh > /dev/null 2>&1 || ! command -v jq > /dev/null 2>&1 ; then \
263268 echo " CI coverage correlation requires gh and jq; using changed-file package selection." ; \
264269 else \
265- COVERAGE_SOURCE_BRANCH=" $( CI_COVERAGE_SOURCE_BRANCH) " ; \
266270 RUN_ID=" $( CI_RUN_ID) " ; \
267271 if [ -z " $$ RUN_ID" ]; then \
268272 RUN_ID=$$(gh run list --workflow "$(CI_WORKFLOW_FILE ) " --branch "$$COVERAGE_SOURCE_BRANCH" --status success --limit 1 --json databaseId --jq '.[0].databaseId' 2>/dev/null || true ) ; \
@@ -305,6 +309,73 @@ test-impacted-go:
305309 CHANGED_GO_PACKAGES=$$(printf '%s\n' "$$CHANGED_GO_FILES" | while IFS= read -r file; do dirname "$$file"; done | sort -u | sed 's|^|./|' ) ; \
306310 echo " Running impacted Go unit tests in changed-file packages: $$ CHANGED_GO_PACKAGES" ; \
307311 fi ; \
312+ SELECTED_GO_TESTS=" " ; \
313+ if command -v gh > /dev/null 2>&1 && command -v jq > /dev/null 2>&1 ; then \
314+ UNIT_RUN_ID=" $( CI_UNIT_RUN_ID) " ; \
315+ if [ -z " $$ UNIT_RUN_ID" ]; then \
316+ UNIT_RUN_ID=$$(gh run list --workflow "$(CI_UNIT_WORKFLOW_FILE ) " --branch "$$COVERAGE_SOURCE_BRANCH" --status success --limit 1 --json databaseId --jq '.[0].databaseId' 2>/dev/null || true ) ; \
317+ fi ; \
318+ if [ -n " $$ UNIT_RUN_ID" ]; then \
319+ UNIT_RESULT_DIR=" $( CI_COVERAGE_DIR) /unit-results" ; \
320+ rm -rf " $$ UNIT_RESULT_DIR" ; \
321+ mkdir -p " $$ UNIT_RESULT_DIR" ; \
322+ if gh run download " $$ UNIT_RUN_ID" --pattern " $( CI_UNIT_TEST_ARTIFACT_PATTERN) " --dir " $$ UNIT_RESULT_DIR" > /dev/null 2>&1 ; then \
323+ UNIT_RESULT_FILE=$$(find "$$UNIT_RESULT_DIR" -type f -name '*.json' | head -n 1 ) ; \
324+ if [ -n " $$ UNIT_RESULT_FILE" ]; then \
325+ IMPACTED_PACKAGE_FILE=" $( CI_COVERAGE_DIR) /impacted-go-packages.txt" ; \
326+ printf ' %s\n' " $$ CHANGED_GO_PACKAGES" | sed ' s|^\./|github.com/github/gh-aw/|' > " $$ IMPACTED_PACKAGE_FILE" ; \
327+ IMPACTED_TEST_CANDIDATES=" $( CI_COVERAGE_DIR) /impacted-go-test-candidates.tsv" ; \
328+ jq -r ' select(.Action == "pass" and .Package != null and .Test != null and (.Test | contains("/") | not) and .Elapsed != null) | [.Package, .Test, (.Elapsed | tostring)] | @tsv' " $$ UNIT_RESULT_FILE" \
329+ | awk ' NR==FNR { pkgs[$$1] = 1; next } $$1 in pkgs { print }' " $$ IMPACTED_PACKAGE_FILE" - \
330+ | sort -u > " $$ IMPACTED_TEST_CANDIDATES" ; \
331+ if [ -s " $$ IMPACTED_TEST_CANDIDATES" ]; then \
332+ SELECTED_GO_TESTS=" $( CI_COVERAGE_DIR) /selected-impacted-go-tests.tsv" ; \
333+ awk ' BEGIN { srand() } { print rand() "\t" $$0 }' " $$ IMPACTED_TEST_CANDIDATES" \
334+ | sort -k1,1n \
335+ | cut -f2- \
336+ | awk -F' \t' -v max=" $( GO_IMPACTED_TEST_MAX_SECONDS) " ' BEGIN { total = 0; selected = 0 } { elapsed = $$3 + 0; if (selected == 0 || total + elapsed <= max) { print; total += elapsed; selected++ } }' \
337+ | sort -t" " -k1,1 -k2,2 > " $$ SELECTED_GO_TESTS" ; \
338+ if [ -s " $$ SELECTED_GO_TESTS" ]; then \
339+ ESTIMATED_DURATION=$$(awk -F'\t' '{ total += $$3 } END { printf "%.3f", total }' "$$SELECTED_GO_TESTS" ) ; \
340+ echo " Running sampled impacted Go unit tests (estimated $$ ESTIMATED_DURATION seconds, max $( GO_IMPACTED_TEST_MAX_SECONDS) s):" ; \
341+ awk -F' \t' ' { print " " $$1 " " $$2 " (" $$3 "s)" }' " $$ SELECTED_GO_TESTS" ; \
342+ else \
343+ SELECTED_GO_TESTS=" " ; \
344+ fi ; \
345+ fi ; \
346+ else \
347+ echo " No unit test result artifact JSON found in run $$ UNIT_RUN_ID; running impacted packages instead." ; \
348+ fi ; \
349+ else \
350+ echo " Unable to download unit test results for run $$ UNIT_RUN_ID; running impacted packages instead." ; \
351+ fi ; \
352+ else \
353+ echo " No successful $( CI_UNIT_WORKFLOW_FILE) run found for branch $$ COVERAGE_SOURCE_BRANCH; running impacted packages instead." ; \
354+ fi ; \
355+ else \
356+ echo " Random impacted test sampling requires gh and jq; running impacted packages instead." ; \
357+ fi ; \
358+ if [ -n " $$ SELECTED_GO_TESTS" ]; then \
359+ awk -F' \t' ' \
360+ BEGIN { current_pkg = " " ; pattern = " " } \
361+ { \
362+ if ($$ 1 ! = current_pkg) { \
363+ if (current_pkg ! = " " ) print current_pkg " \t^(" pattern " )$$ " ; \
364+ current_pkg = $$ 1; \
365+ pattern = $$ 2; \
366+ } else { \
367+ pattern = pattern " |" $$ 2; \
368+ } \
369+ } \
370+ END { \
371+ if (current_pkg ! = " " ) print current_pkg " \t^(" pattern " )$$ " ; \
372+ } \
373+ ' "$$SELECTED_GO_TESTS" | while IFS=" " read -r pkg pattern; do \
374+ echo " Running impacted Go unit tests in $$ pkg with pattern $$ pattern" ; \
375+ go test -v -parallel=4 -timeout=10m -short -run " $$ pattern" " $$ pkg" || exit 1; \
376+ done || exit 1; \
377+ exit 0; \
378+ fi ; \
308379 # Use -short to exclude integration tests and keep execution to unit-test scope. \
309380 printf ' %s\n' " $$ CHANGED_GO_PACKAGES" | tr ' \n' ' \0' | xargs -0 -r go test -v -parallel=4 -timeout=10m -short
310381
0 commit comments