All checks were successful
check / check (push) Successful in 3m13s
script/cibuild was a bare `docker build .`. On an unchanged tree Docker served the check RUN layers from cache, so make fmt-check, make lint and make test never executed - and the build still exited 0. Measured at 221ms with zero ok lines and every check layer CACHED, against 162s for a real run. CI showed the same signature: 6 second "successes" on main. An ARG CHECK_EPOCH now sits immediately above the check RUNs in both stages - each stage declares its own, since ARG scope is per-stage - and script/cibuild passes a fresh value per invocation. Dependency and module layers sit above the ARG and still cache, so this does not make every build cold. The epoch is assigned before the build rather than inlined into the --build-arg. Under `set -eu` a command substitution that fails inside an argument does not abort the script: CHECK_EPOCH would become an empty string, an empty string is a constant, a constant CHECK_EPOCH restores the cached false green, and the guard would silently disarm itself while still exiting 0. As a bare assignment, set -e catches a failing date and no build starts. The README and Dockerfile state the guarantee conditionally. It holds per build context and CHECK_EPOCH value, and depends on script/cibuild passing a fresh one - a bare `docker build .` with no --build-arg still replays the check layers from the second consecutive run onward. That residual gap is tracked in #91 along with the remaining upstream hardening. Verification is recorded once, in the PR's verification comment, rather than restated with differing numbers in three places.
33 lines
1.4 KiB
Bash
Executable File
33 lines
1.4 KiB
Bash
Executable File
#!/bin/sh
|
|
# script/cibuild: run the CI build. The Dockerfile does not run
|
|
# script/check; it runs `make fmt-check` and `make lint` in its lint
|
|
# stage and `make test` in its builder stage. A successful build
|
|
# implies those three passed, provided they actually ran -- which is
|
|
# what the CHECK_EPOCH below is for.
|
|
# Generic: needs no adaptation. The Gitea workflow runs this on push.
|
|
set -eu
|
|
|
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
|
|
|
main() {
|
|
cd "$ROOT"
|
|
# The Dockerfile's check layers are keyed on CHECK_EPOCH, so a
|
|
# fresh value here is what forces them to re-run: without it an
|
|
# unchanged tree replays them from cache, the checks never execute,
|
|
# and the build still exits 0. The ARG sits immediately above the
|
|
# check RUNs, so dependency and module layers still cache.
|
|
#
|
|
# Assign the epoch on its own line rather than inline in the
|
|
# argument. Under `set -eu` a command substitution that fails
|
|
# inside an argument does NOT abort the script: CHECK_EPOCH would
|
|
# become an empty string, an empty string is a constant, and a
|
|
# constant CHECK_EPOCH is exactly the cached-check false green this
|
|
# script exists to prevent -- so the guard would disarm itself and
|
|
# still exit 0. As a bare assignment, `set -e` catches a failing
|
|
# `date` and no build starts.
|
|
epoch="$(date +%s)"
|
|
docker build --build-arg CHECK_EPOCH="$epoch" .
|
|
}
|
|
|
|
main "$@"
|