Build with --no-cache so the check layer actually runs (closes #26)

script/cibuild was a plain `docker build .` and the Dockerfile does
`COPY . .` followed by `RUN make check`, so on an unchanged tree Docker
served the check layer from cache: the suite never ran and the build
still exited 0. Measured here before the change, a second run on a
byte-identical tree returned in 0.286s with `RUN make check` CACHED.
script/cibuild and script/docker now pass --no-cache. The canonical text
asserting that a bare `docker build .` proves the checks ran was wrong in
REPO_POLICIES.md, both checklists and the Go styleguide, and is corrected
in all of them.

Model: opus-5
This commit is contained in:
2026-09-08 04:58:31 +00:00
parent fbec5a523b
commit 9c4edd611b
8 changed files with 55 additions and 26 deletions

View File

@@ -1,6 +1,6 @@
---
title: Repository Policies
last_modified: 2026-08-19
last_modified: 2026-09-08
---
This document covers repository structure, tooling, and workflow standards. Code
@@ -60,10 +60,10 @@ style conventions are in separate documents:
prerequisite since nvm requires bash. yarn is then pinned via
`corepack prepare yarn@<version> --activate`. Never install "latest" or "lts";
always exact versions. `script/cibuild` runs the CI build: it changes to the
repo root and runs `docker build .`; the Gitea workflow calls it. Four further
scripts are our own extensions to the standard: `script/check` runs
`script/test`, `script/lint`, and `script/fmt-check`; `script/precommit` is
what the git pre-commit hook runs, and it calls `script/check`;
repo root and runs `docker build --no-cache .`; the Gitea workflow calls it.
Four further scripts are our own extensions to the standard: `script/check`
runs `script/test`, `script/lint`, and `script/fmt-check`; `script/precommit`
is what the git pre-commit hook runs, and it calls `script/check`;
`script/install-precommit` installs the git pre-commit hook (the `make hooks`
target shims to it); and `script/projectname` (literally that filename) simply
outputs the project's name. Scripts that need the name call
@@ -99,6 +99,15 @@ style conventions are in separate documents:
`yarn.lock`, `go.mod` + `go.sum`, etc.) before running it so the bootstrap
layer stays cached until dependencies change.
- **Any build that runs checks is built with `--no-cache`.** Docker invalidates
a `COPY` layer only when the copied content changes, so on an unchanged tree
the check `RUN` is served from cache, nothing executes, and the build still
exits 0. `script/cibuild` and `script/docker` therefore pass `--no-cache`, and
a bare `docker build .` is not evidence that anything ran: a sub-second build
reporting success is a cache hit, not a result. Never invalidate by pruning —
`docker builder prune` and friends destroy a build cache shared with every
other build on the host.
- **Dockerfiles must use a separate lint stage for fail-fast feedback.** Go
repos use a multistage build where linting runs in an independent stage based
on the `golangci/golangci-lint` image (pinned by hash). This stage runs
@@ -167,9 +176,10 @@ style conventions are in separate documents:
artifacts or heavier dependencies.
- Every repo should have a Gitea Actions workflow (`.gitea/workflows/`) that
runs `script/cibuild` (which runs `docker build .`) on push. Since the
Dockerfile already runs `make check`, a successful build implies all checks
pass.
runs `script/cibuild` (which runs `docker build --no-cache .`) on push. Since
the Dockerfile already runs `make check`, a successful build implies all
checks pass — an implication that holds only because of the `--no-cache`
above.
- Use platform-standard formatters: `black` for Python, `prettier` for
JS/CSS/Markdown/HTML, `go fmt` for Go. Always use default configuration with