make test-integration is a silent no-op — no file carries the integration build tag #69
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Makefile:70-71defines:But
grep -rn '//go:build' --include=*.go .returns nothing. No filein the repo carries a build tag of any kind, so
-tags=integrationselects no additional files and
make test-integrationis an exactduplicate of
make test.The practical effect is worse than a useless target:
internal/vaultik/ integration_test.go(1,033 lines of full chunk → pack → encrypt → upload→ restore round-trips) runs unconditionally on every
make test, andanyone reading the Makefile reasonably concludes it does not.
Related risk in the same area:
script/testrunsgo test -race -timeout 30s ./.... That is a per-package 30-secondtimeout applied to
internal/vaultik, which does full round-trips under-race. Measured locally it takes ~6.7s, andinternal/database~6.9s,but on slower CI this is the first thing that will flake.
Definition of done
Decide and implement one of:
//go:build integrationsomake testis fast andmake test-integrationis meaningfully different; ortest-integrationtarget and itsscript/counterpart if one exists, and document that
make testrunseverything.
State which was chosen and why in the commit message. Option (a) is
preferred if the round-trip tests are slow enough to be worth gating;
otherwise (b) — a target that lies is worse than no target.
If (a):
make testandmake test-integrationdemonstrably rundifferent sets of tests, and CI runs both. The integration set must
still run somewhere in CI, not silently drop out of coverage.
The
-timeout 30sinscript/testis reviewed against actualmeasured runtimes with margin for slow CI, and either raised with a
comment explaining the chosen value, or explicitly confirmed as
adequate. Do not leave it unexamined.
Per repo policy,
makeandscript/entrypoints only — no rawgo testinvocations introduced.make checkgreen.New evidence raising the priority of this issue's timeout item, plus one
thing that checks out clean.
The timeout is a live flake risk as of today
The shared BuildKit cache on this host was destroyed — a subagent on
another repo ran
docker builder prune -af, wiping ~41 GB. Every sessionlost its Docker layer cache, so builds and containerised test runs are
cold.
script/testruns:That is a per-package 30-second timeout, under
-race, and it nowruns against an empty Go build cache inside a fresh container. A sibling
repo hit exactly this failure within minutes:
timeout 30 go test ./...died on an empty build cache in a fresh container, then passed in 11s on
retry.
vaultik's measured warm timings leave less headroom than they appear to:
internal/database~5.9s andinternal/vaultik~6.2s warm. Compilationof a large
-racebuild on a cold cache is charged against that same30-second budget, and the margin is thinner than the numbers suggest.
Practical consequence right now: a test timeout observed today is
more likely cold-cache compilation than a real defect. Retry before
treating it as one, and say in any report whether the run was cold.
This strengthens the case for definition-of-done item 3 — the timeout
should be reviewed against a genuinely cold cache with margin for slow
CI, not just against warm local runs, and the chosen value should carry a
comment explaining it.
What checks out clean
script/test's retry does not swallow failures. The sibling-repo bugwhere a verbose rerun could convert a failure into a pass does not exist
here:
The unconditional
exit 1after the rerun guarantees a non-zero exitregardless of what the second run reports, and the header comment states
that intent outright. Verified by reading, not assumed. Recording it here
because it is a plausible place to look for a fourth false-green
mechanism in this repo, and it is genuinely sound.
Worth noting the retry does double the work on failure, so a cold-cache
timeout costs two full
-raceruns before reporting. Not a correctnessproblem, but relevant when judging what timeout value is appropriate.
Plan
Implementing this together with #93 as a single PR — both change
script/test, and DoD item 3 here (the-timeout 30sbudget) has to bedecided against the uncached behaviour #93 introduces, or it would be
tuned against runs that did no work.
Item 1: choosing (b), delete the target
Confirmed the premise:
grep -rn '//go:build' --include=*.go .returnsnothing, so
-tags=integrationselects no extra files andmake test-integrationis byte-for-bytemake testplus-v.I intend to take (b) — delete
test-integrationand document thatmake testruns everything, including the round-trips ininternal/vaultik/integration_test.go. The DoD says (a) is preferred"if the round-trip tests are slow enough to be worth gating", and
measured on
mainat3f9c2e5they are not: a full coldmake testacross all 18 packages under
-raceis 15.9s, with the two heaviestpackages at 6.6s (
internal/vaultik) and 6.4s (internal/database).Splitting the round-trips out would save a few seconds off a
sixteen-second suite, in exchange for a build-tag scheme and a second CI
path that must be kept wired up. Given that this repo has now found five
separate ways for a gate to report a green it did not earn (#78, #80,
#85, #88, #93), adding a mechanism whose failure mode is "some tests
silently stopped running" is a bad trade for those seconds. (b) also
discharges DoD item 2 for free: nothing can drop out of CI coverage if
nothing is conditional.
Item 3: the timeout, and a claim I want to check first
The comment above states that cold-cache compilation is charged against
the 30s budget. I do not believe it is:
-timeoutis handed to thecompiled test binary as
-test.timeout, and that clock starts insidetesting.M.Run, after compilation and linking have finished. Thesibling-repo failure cited was
timeout 30 go test ./...— a shelltimeoutaround the whole invocation, which does include compilation.Different mechanism.
I am measuring this rather than asserting it: a cold containerised run
via
script/cibuildhas an emptyGOCACHEinside the image, so ifcompilation counted, its per-package durations would be far larger than
the warm host ones. If they come back close to warm, the claim is
disproved and the real risk is only slow/contended CI executing the
tests themselves more slowly.
Either way the value gets reviewed and carries a comment. My prior is
that 30s is too thin — not because compilation counts, but because a
-timeoutis a hang backstop rather than a performance budget, and4.5x over the slowest measured package is not enough margin for a
loaded CI runner. Final number and its supporting measurement will be in
the PR.
Correcting a claim I made on this issue. It was wrong, and it was the
premise for treating the timeout as urgent.
I wrote:
That is false.
-timeoutis passed to the compiled test binary as-test.timeout, and that clock starts insidetesting.M.Run— aftercompilation and linking have completed. Build time is not charged against
it.
Measured rather than argued, in PR #98. A containerised run with an empty
GOCACHEspent 46.3 seconds compiling before the first resultappeared, then reported per-package durations essentially identical to a
warm host run:
internal/databaseinternal/vaultikinternal/snapshotIf compilation were charged, the cold column would be tens of seconds
larger. It is within ~11%.
Where my error came from: I generalised from a sibling repo's failure
that was reported as
timeout 30 go test ./...— a shelltimeoutwrapping the entire invocation, which does include compilation. That is
a different mechanism from the
-timeoutflag, and the analogy does notcarry. I should have checked which of the two vaultik actually used
before propagating the concern, especially since I quoted vaultik's
script/testline in the same comment.The conclusion survives, for a different reason. The real exposure was
margin, not compilation. The slowest package measured anywhere — warm or
cold, host or container — is
internal/databaseat 8.113s on a coldcontended containerised run. Against that, 30s left only 3.7x headroom,
which is thin for a throttled CI runner, and
script/testdoubles thework on failure because it reruns verbosely. Raised to 120s, about
15x, which still bounds a hung package plus its rerun to a few minutes.
The framing in the PR is the right one and worth keeping: a
-timeoutisa hang backstop, not a performance budget. Its job is to turn a
deadlocked test into a stack dump rather than a wedged CI job, so it
should sit far above the slowest legitimate runtime rather than snugly
above it. Nothing is gained by failing at 30s that is not gained by
failing at 120s.
Recording this prominently because "cold cache eats your timeout" is a
plausible-sounding claim that would have propagated to other repos
unchallenged, and because an implementer disproving their instructions
with measurement is exactly the behaviour I want — not an argument to be
smoothed over.