Run script/bootstrap in the Docker build stage (closes #42)
All checks were successful
check / check (push) Successful in 1m16s
All checks were successful
check / check (push) Successful in 1m16s
Canonical REPO_POLICIES.md:97 requires Dockerfiles to install development prerequisites by running script/bootstrap rather than duplicating installs inline. The build stage did the opposite: an inline `apk add --no-cache make` and its own `go mod download`, so it maintained a second, independent notion of the toolchain — the local-versus-CI divergence #24 exists to close, reintroduced one layer down. The stage now copies script/ plus go.mod/go.sum and runs script/bootstrap, which ends in `go mod download`. COPY --from=lint /usr/bin/golangci-lint is kept and moved above the bootstrap layer. It is the only edge making this stage depend on the lint stage, so removing it as redundant would silently stop the build gating on lint. Copying it first also puts it on PATH before bootstrap runs, so bootstrap's version check compares the lint stage's linter against the pin on every build: the two stages are now provably one toolchain rather than two that happen to agree, and bootstrap does not pay for a from-source build of its own linter. $GOPATH/bin joins PATH so that if the copied binary ever stops matching the pin, bootstrap's reinstall lands somewhere PATH resolves instead of failing its own verification. All of it sits above ARG CHECK_EPOCH, and the chown and USER builder still precede make check.
This commit is contained in:
41
TODO.md
41
TODO.md
@@ -29,6 +29,47 @@
|
||||
|
||||
# Completed Steps
|
||||
|
||||
- install the Docker build stage's prerequisites by running
|
||||
`script/bootstrap` instead of `apk add --no-cache make` inline
|
||||
(2026-08-09, branch `dockerfile-bootstrap`, closes #42): canonical
|
||||
`REPO_POLICIES.md:97` requires it, and the inline install left the
|
||||
build stage maintaining its own notion of the toolchain — exactly
|
||||
the divergence #24 exists to close, one layer down. The stage now
|
||||
copies `script/` plus `go.mod`/`go.sum` and runs `script/bootstrap`,
|
||||
which ends in `go mod download`, so the separate invocation of that
|
||||
is gone. `COPY --from=lint /usr/bin/golangci-lint` stays, and moves
|
||||
above the bootstrap layer. It is the only edge making this stage
|
||||
depend on the lint stage, so deleting it as redundant would end
|
||||
fail-fast linting silently; putting it first also means bootstrap's
|
||||
version check now compares the lint stage's linter against the pin
|
||||
on every build, which is what makes the two stages provably one
|
||||
toolchain instead of two that happen to agree. Letting bootstrap
|
||||
install its own linter here would have reintroduced the second
|
||||
toolchain and paid for a from-source build of it. `$GOPATH/bin`
|
||||
joins `PATH` so that if the copied binary ever stops matching the
|
||||
pin, bootstrap's reinstall lands somewhere `PATH` resolves rather
|
||||
than failing its own verification. Everything added sits above
|
||||
`ARG CHECK_EPOCH`, and the `chown` and `USER builder` still precede
|
||||
`make check`. Verified: bootstrap runs clean under Alpine's `sh` and
|
||||
its `apk` branch, installing `git` and `make` and finding the copied
|
||||
linter already at the pin; a second build served the bootstrap and
|
||||
dependency layers `CACHED` while both gates ran with a fresh epoch;
|
||||
a planted `unused` finding failed the build at the lint gate in
|
||||
48.9s with the build stage's `make check` never starting; and the
|
||||
suite run in the image as `--user 0:0` fails
|
||||
`TestScanHardlinkRunFailsTogether`, so the drop to the unprivileged
|
||||
user is still load-bearing. That last check needs the Go test cache
|
||||
disabled — the first attempt reported `ok ... (cached)` as root,
|
||||
reusing the result the build-time run had left in the shared cache,
|
||||
which would have read as a pass. Build wall time, on a shared host
|
||||
running many concurrent builds and so noisy: 2m13s on an unchanged
|
||||
tree, 2m17s and 4m29s for two builds after a source change, 5m14s
|
||||
cold. Only the cold one breaches the policy ceiling, and not because
|
||||
of this change — `chown -R builder:builder /src /home/builder` walks
|
||||
the module cache and re-runs on every source change, and it alone
|
||||
varied between 77s and 210s across those four builds, which is also
|
||||
the whole spread in the totals. The same cold measurement against
|
||||
`main` is 5m03s with a 209s `chown`. Filed as #43
|
||||
- bust the Docker layer cache for the gate steps, so `script/cibuild`
|
||||
and `script/docker` cannot report a green they did not earn
|
||||
(2026-08-09, branch `cibuild-cache-bust`, closes #32): both scripts
|
||||
|
||||
Reference in New Issue
Block a user