Keep Go's build cache in check builds (closes #113)
check / check (push) Canceled after 0s

script/lint, script/test, script/cibuild and script/docker pass a new
CACHEBUST build argument on every build in place of --no-cache, which
empties every cache mount. Every Dockerfile stage declares ARG
CACHEBUST first, so every RUN step still runs on every check build.
The canonical Go Dockerfile mounts Go's build cache on the steps that
compile and runs both go test runs with -count=1, so no test result is
reused. REPO_POLICIES.md, both checklists, the Go styleguide and the
README say so. A stage without the ARG line is served from cache, so a
repository re-vendors the scripts and the ARG lines in one commit.

Model: opus-5-5
This commit is contained in:
2026-10-15 09:09:17 +00:00
parent f9e23ccae3
commit 9bd1f006f4
11 changed files with 164 additions and 90 deletions
+15 -5
View File
@@ -1,6 +1,6 @@
---
title: Existing Repo Checklist
last_modified: 2026-10-08
last_modified: 2026-10-15
---
Use this checklist when beginning work in a repo that may not yet conform to our
@@ -49,6 +49,15 @@ with your task.
`--target` names it, so a lost `COPY --from=` edge leaves `docker build .`
passing while the gate never runs. Confirm by planting a violation, not by
reading the file.
- [ ] Every stage declares `ARG CACHEBUST` as its first line after `FROM`. The
`script/` builds pass a new `CACHEBUST` value on every build, which reruns
every `RUN` step and keeps Go's build cache; `--no-cache` would empty it.
A stage without the `ARG` line is served from cache on an unchanged tree,
so the scripts and the `ARG` lines are re-vendored in one commit.
- [ ] Go: the steps that compile (`golangci-lint run`, `go test`, `go build`)
mount Go's build cache (`--mount=type=cache,target=/root/.cache/go-build`)
and nothing else, and both `go test` runs carry `-count=1`, as in the
canonical Go `Dockerfile` in `REPO_POLICIES.md`
- [ ] The gate phases invoke their tools directly, never through `make lint` or
`script/test` — those are themselves a `docker build` and would recurse
inside a build step
@@ -133,7 +142,7 @@ with your task.
- [ ] README has an **Entrypoints** section documenting the `script/`
entrypoints and linking the standard
- [ ] `script/lint` and `script/test` each run
`docker build --no-cache --target <phase> --output type=cacheonly .`,
`docker build --build-arg CACHEBUST="$(date +%s)-$$" --target <phase> --output type=cacheonly .`,
which builds their phase by name and writes no image, and no host
invocation anywhere in the repo can produce a lint verdict — grep for the
linter's own name across `script/`, the `Makefile` and CI config, not just
@@ -146,7 +155,8 @@ with your task.
`script/cibuild` tag theirs. A build that writes an untagged image leaves
one behind on every run, on every host and CI runner.
- [ ] `script/cibuild` runs `script/bootstrap` before `script/check`, and builds
the image with `--no-cache`. Without the bootstrap the CI run dies in
the image with a new `CACHEBUST` value on every build, like every
`docker build` in `script/`. Without the bootstrap the CI run dies in
`script/fmt-check`, which runs the formatter on the host and finds nothing
installed.
- [ ] `script/fmt` and `script/fmt-check` pick their `yarn` with the same test
@@ -211,8 +221,8 @@ with your task.
- [ ] `script/cibuild` succeeds in a fresh clone on a host carrying what CI has
(the runner image `docker.gitea.com/runner-images:ubuntu-latest`: docker,
git and node 24, with no yarn on `PATH`), and demonstrably executed the
checks — a sub-second build, or `CACHED` on a gate layer, means nothing
ran
checks — a sub-second build, or `CACHED` on a gate's `RUN` step, means
nothing ran
- [ ] A planted lint violation fails both `make lint` and a plain
`docker build .`; revert it afterwards
- [ ] Commit and merge fixes before starting your actual task