Skip to content

fix: test_go_race times out on internal/app in CI (Go's 10m per-package limit) - #346

Merged
danielhanold merged 20 commits into
mainfrom
fix/test-go-race-times-out-on-internal-app-in-ci-go-s-10m-per-pa
Sep 28, 2026
Merged

danielhanold merged 20 commits into
mainfrom
fix/test-go-race-times-out-on-internal-app-in-ci-go-s-10m-per-pa

Conversation

@danielhanold

Copy link
Copy Markdown
Owner

↩ Change 0465 — test_go_race times out on internal/app in CI (Go's 10m per-package limit)

↩ Change 0465 — test_go_race times out on internal/app in CI (Go's 10m per-package limit) (change file)

Summary

The CI race gate (tests/test_go_race.sh) intermittently hit Go's 10m per-package timeout in internal/app. The cause: about 337 default tests there spawn real git, and they took about 225s of the package's ~238s under -race.

  • Enforced invariant. A default-build-only guard (internal/app/nogit_guard_test.go) puts a refusing git shim first on PATH and fails the package on any attempt, including tests that swallow the error. Tagged builds (integration, e2e) get a no-op twin. TestMain's supervisor/guardian re-exec routing is unchanged. The guard is mutation-tested.
  • Re-partition. All 337 offenders moved behind //go:build integration into 12 new plain shard runners (tests/test_go_integration_app_*.sh). Five genuinely concurrent tests went to the existing race shard. tests/test_go_integration_contract.sh is green.
  • Result. go test -race ./internal/app/ went from ~238s to ~14s.
  • Backstop. test_go_race.sh passes -timeout 8m and prints a readable overrun line, pinned by internal/repoguard/race_gate_timeout_test.go.
  • Budget alerts across worktrees. The suite-runner budget-state key is now the repo-relative path (budgetKeyPath), so overruns accumulate across .worktrees/* and serial confirmation can fire.
  • Budget rows. Rows were re-measured.
    • Finding: test_go_race.sh still measures ~67s solo against its 60 row. internal/app no longer drives this; internal/repository/transaction and internal/workspace now do. Those packages are follow-up work; this PR does not grant a larger ceiling.

Results: docs/results/2026-09-28-test-go-race-times-out-on-internal-app-in-ci-go-s-10m-per-pa-results.md. Human action after merge: confirm several green CI source-gate runs.

Review

Reviewed by docket-review-deep. The rung is the highest build profile, premium, and the diff is over 1500 lines. The review found 0 blockers, 1 important and 3 minors.

# Severity Finding Disposition
1 important 4m backstop too tight for projected CI times fixed — ed88796 (8m + floor assertion)
2 minor test_go_toolchain.sh row raised 55→60 out of scope fixed — 0361260 (reverted to 55)
3 minor guard header overclaimed coverage fixed — 0361260 (known limits documented)
4 minor stale renamed-file references in comments fixed — 0361260

Build notes:

  • Task 10 escalated standard→premium to split an over-budget shard.
  • Task 14 needed a same-profile continuation after its worker's scope halted on a self-inflicted worktree edit during a live drive.

Build evidence

command: go run ./cmd/docket development test
result: green
head_sha: 6bf5932
ran_at: 2026-09-28T10:00:42Z

Budget report (green run, screening only; nothing serially confirmed): BUDGET WATCH lines for:

  • test_go_race
  • test_go_toolchain
  • app_closeout
  • app_rebaserecovery
  • finalize_e2e
  • app_merge

… corpus never runs real git)

Docket-Plan-Path: docs/superpowers/plans/2026-09-28-test-go-race-times-out-on-internal-app-in-ci-go-s-10m-per-pa.md
… tag (TestIntegrationGateCancel, change 0465)
…n tag (TestIntegrationGateVerdict, change 0465)
…e integration tag (TestIntegrationGateFence, change 0465)
…hind the integration tag (TestIntegrationGateCompletion, change 0465)
…tegration tag (TestIntegrationGateEpoch, change 0465)
…the integration tag (TestIntegrationGateArm, change 0465)
…ind the integration tag (TestIntegrationGateLifecycle, change 0465)
…tion tag (TestIntegrationFinalizeOps, TestIntegrationFinalizeRebaseOps, change 0465)

The 38 normal finalize real-git tests measured 56s solo in one runner (row 65),
over the 60s parallel-lane ceiling, so they are split across two runners with
disjoint prefixes: TestIntegrationFinalizeRebaseOps (the 23 finalize_rebase
continue/resolver-budget/gate-halt/receipt tests, 35s solo, row 40) and
TestIntegrationFinalizeOps (resolver-reserve, block, publish and PR-publish,
21.5s solo, row 30). TestFinalizeResolverReserveConcurrent joins the race shard
as TestRaceIntegrationAppConcurrencyFinalizeResolverReserveConcurrent (race
shard 29s solo, row 35 unchanged).
…egration tag (TestIntegrationEvidence, change 0465)
…d the integration tag (TestIntegrationRecordOps, change 0465)
…l-git tests behind the integration tag (TestIntegrationContextProbe, change 0465)
…t_go_race (change 0465)

tests/test_go_race.sh now passes RACE_TIMEOUT="4m" to `go test -race` and adds
an assert that names the backstop ("no package ran past the 4m -timeout
backstop") plus the offending FAIL line and a PARTITION AND LANE remedy on
overrun, instead of Go's 10m goroutine-dump panic. Header PARTITION AND LANE
paragraph updated for the change-0465 no-real-git invariant; new BACKSTOP
TIMEOUT paragraph.

Measurement (Step 1, CI-equivalent cap):
`GOMAXPROCS=2 go test -race -count=1 -p 2 ./...` exit 0; slowest packages
internal/repository/transaction 48.654s, internal/repository/workspace 44.1s,
internal/gatedrive 39.4s; internal/app 13.8s. 4 x 48.654s = 194.6s -> 4m
(>= 3m minimum, < 8m escalation bound).

Behavioral tests (internal/repoguard/race_gate_timeout_test.go) run a copy of
the real wrapper against a fake `go`; mutation probes (drop -timeout; drop the
backstop assert) each turn the matching test red.
…hange 0465, review finding)

Review finding (important): RACE_TIMEOUT="4m" in tests/test_go_race.sh was sized
from an idle local run (internal/repository/transaction 48.7s at -p 2). The spec's
own data shows CI ~2.4-3.8x slower than local (238s vs 581-908s), projecting that
package to ~120-230s against a 240s limit, so the backstop could trip
intermittently. Raise it to 8m (>= 2x the worst projection, below Go's 10m
default), rewrite the header derivation, and pin the floor in
TestRaceGatePassesTimeoutBackstopBelowGoDefault.
- revert tests/test_go_toolchain.sh budget 60 -> 55 (out of spec scope)
- nogit guard header states its known bypass limits instead of overclaiming
- repoint stale *_test.go file references in maintained comments
@danielhanold
danielhanold merged commit bec2c9d into main Sep 28, 2026
7 checks passed
@danielhanold
danielhanold deleted the fix/test-go-race-times-out-on-internal-app-in-ci-go-s-10m-per-pa branch September 28, 2026 10:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant