Skip to content

Commit 8f7a2a9

Browse files
Copilotpelikhan
andauthored
Limit impacted Go test sampling
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
1 parent 6f788eb commit 8f7a2a9

1 file changed

Lines changed: 72 additions & 1 deletion

File tree

Makefile

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ CI_COVERAGE_DIR ?= /tmp/gh-aw-ci-coverage
1717
CI_COVERAGE_ENABLED ?= 1
1818
CI_COVERAGE_SOURCE_BRANCH ?= main
1919
CI_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
2226
LDFLAGS=-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

Comments
 (0)