script/cibuild reports a green it did not earn: make check is served from Docker cache #89
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?
Reproduced in this repo, on
3bfbb3fscript/cibuildruns a baredocker build .with no cache control. TheDockerfiledoesCOPY . .and thenRUN make fmt-check,RUN make lint,RUN make test. Docker's layer cache keys on the content of the buildcontext, so on an unchanged tree every check layer is a cache hit, the
suite never executes, and the build still exits 0.
Measured here, back to back, same tree, no changes in between:
0.6 seconds, exit code 0, nothing ran. A "green CI" that proves nothing.
Why this matters more here than elsewhere
The Gitea workflow calls
script/cibuild, andREADME.mdstates the claimplainly: "a successful build implies all checks pass." That implication is
false as written. Every "docker build green" claim in this repo's PR history
is only as trustworthy as whether the tree happened to differ from a previous
build — which is not something a reviewer can see from the exit code.
It compounds with two open issues:
script/testrunsgo test -v --timeout 10s ./...with no-raceand no-cover. A weak test command, cached, is doubly weak.failure this cache masks is precisely the intermittent one.
A cached green over a weak test script is the worst combination: the check
that would have caught the flake is the check that did not run.
Definition of done
script/cibuildcannot report success without actually executingmake fmt-check,make lint, andmake test.script/cibuildtwice in a row on an unchanged tree executes thechecks both times. Demonstrate it: run it twice, show the second run's
duration and that the check layers are not
CACHED.go mod download, and theyarn installin the
mdfmtstage once #69 lands) stay cached, so the build does notregress to a full cold build every time. Docker builds must still complete
in under 5 minutes per policy.
README.md's "a successful build implies all checks pass" is true again,or reworded to match reality.
Implementation requirements
promptsrepo as issue #26: addARG CHECK_EPOCHin theDockerfileimmediately above the firstcheck-running
RUN, and havescript/cibuildpass--build-arg CHECK_EPOCH="$(date +%s)". The changing ARG invalidateseverything from that point down while leaving the dependency layers above
it cached. Prefer this over
--no-cache, which would also discardgo mod downloadand blow the 5-minute budget.ARGdeliberately. It must sit belowgo mod downloadandabove the first
RUN make ...in each stage that runs checks. ThisDockerfile has two such stages (
lintandbuilder), and after #69 landsa third (
mdfmt) — all of them need it, or the uninvalidated stage keepsserving stale greens.
one you tested. The failure mode of a partial fix is indistinguishable
from a working one at the exit code.
after the change and state it in the PR.
promptsfix rather than inventing a local variant, sothis repo stays alignable with the canonical template.
(closes #89).Note
Do not backfill-invalidate the existing evidence on PR #59 and PR #88 on
account of this. Both were separately verified with cache control
(
--no-cache-filteron the check stages for #59, a dedicated cold buildxbuilder for #88), and #59's head is being re-verified with a full
--no-cacherun before it merges. This issue is about making that rigourautomatic instead of dependent on whoever happens to remember.