docs: trim the lint-gate comments to the traps (closes #44)
Comments and documentation only; the docker build invocation and its three flags are byte-identical and .dockerignore's effective rules are unchanged. script/lint and Dockerfile.lint stated how the shape was derived — why two stages, why `golangci-lint config verify` was omitted, what earlier drafts of the comments claimed. That is in the history. What survives is the three traps, each of which yields a green run over an unlinted or partly linted tree: --target and --no-cache-filter must both stay with $stage matching the stage name in Dockerfile.lint; --target checks that the stage exists, not that it runs golangci-lint, and halts the build there; and .dockerignore decides what reaches the container, so excluding a self-contained Go file drops it from the lint silently. The TODO.md entry loses its "Hardened" and "Corrected" paragraphs, which argued with earlier versions of themselves, and keeps the flags, the durable property, the three unguarded seams, and the evidence that the gate was verified rather than assumed.
This commit is contained in:
62
TODO.md
62
TODO.md
@@ -44,57 +44,25 @@ is finished.
|
||||
branch that was genuinely red with a `goconst` finding reported `0 issues` off
|
||||
the shared host cache; a container per run has its own cache and lock.
|
||||
|
||||
Two deliberate divergences from the `sneak/homoicon` reference. The image
|
||||
has two stages rather than one — a cached `deps` stage holding
|
||||
`go mod download`, then `FROM deps AS lint` with the copy and the lint run —
|
||||
and `script/lint` builds with `--no-cache-filter=lint`. Caching of the lint
|
||||
result is explicitly waived (a cached build lints nothing), and splitting
|
||||
the stages means busting the lint layer does not also re-fetch the module
|
||||
cache over the network on every run. And `golangci-lint config verify` is
|
||||
left out: it resolves its JSON schema over a live, unpinned HTTPS call,
|
||||
which is an unpinned network input inside the one step whose purpose is a
|
||||
pinned reproducible gate, and a schema-host outage would surface as a red
|
||||
build. `golangci-lint run` already fails on a malformed config.
|
||||
`script/lint` builds with `--target "$stage"`, `--no-cache-filter="$stage"`
|
||||
and `--output=type=cacheonly`. The durable property to check when touching
|
||||
any of this: the lint stage executes on every run and is never served from
|
||||
cache. Three things no tooling checks, left to whoever edits the gate —
|
||||
`$stage` must match the stage name in `Dockerfile.lint`; that stage must
|
||||
stay the one running `golangci-lint`, since `--target` halts the build
|
||||
there; and `.dockerignore` governs what reaches the container, so excluding
|
||||
a self-contained Go source drops it from the lint silently.
|
||||
|
||||
Verified rather than assumed, since a green docker build is the classic
|
||||
false green: two consecutive runs on an unchanged tree each showed the
|
||||
`golangci-lint run` layer executing and reporting `0 issues.` while the
|
||||
`deps` layers reported `CACHED`, and a deliberate `indent-error-flow`
|
||||
violation failed the build naming that finding plus the `unused` one before
|
||||
a revert went clean again. The durable property to check when touching any
|
||||
of this is that the lint stage executes on every run and is never served
|
||||
from cache; wall-clock durations vary per host and per run, so they are not
|
||||
recorded here.
|
||||
|
||||
Hardened 2026-08-10 after review. `script/lint` now also passes `--target`
|
||||
and `--output=type=cacheonly`. `--target` is what makes `--no-cache-filter`
|
||||
trustworthy: BuildKit silently ignores the filter when no stage matches its
|
||||
argument, so a rename or typo of the `lint` stage would have left the lint
|
||||
layer cached and `script/lint` green having linted nothing — the same false
|
||||
green in a new place. `--target` fails loudly on a name that is not in the
|
||||
file. `--output=type=cacheonly` skips the image export: nothing consumes the
|
||||
image (the deliverable is an exit code), and exporting it cost seconds per
|
||||
run and left a dangling image behind each time.
|
||||
|
||||
Corrected 2026-08-10 after a second review, which was right to reject the
|
||||
claim first made here that the two flags "validate each other". They did
|
||||
not: `--target` validates only its own argument, so a typo confined to
|
||||
`--no-cache-filter` still built `CACHED` at exit 0 — the original defect,
|
||||
surviving in the narrow case. The duplicated stage name was the defect, so
|
||||
it is now written once, as `stage=lint` in `script/lint`, and passed to both
|
||||
flags. The true property is that there is only one name to get wrong, and
|
||||
`--target` rejects it loudly if it is not a stage in `Dockerfile.lint`, so a
|
||||
typo or a stale rename is a hard error rather than a silent skip. What
|
||||
remains on the editor, and is not checked by anything: `$stage` must name
|
||||
the stage that actually runs `golangci-lint`. `--target` verifies the name
|
||||
exists, not that it is the right stage, and it stops the build there — so
|
||||
moving the lint step to another stage, or adding a stage after it, would go
|
||||
unnoticed. The same applies to `.dockerignore`, which is part of this gate
|
||||
rather than housekeeping: only what reaches the container is linted, so
|
||||
excluding a Go source there drops it from the lint silently — verified, a
|
||||
planted violation plus that one path in `.dockerignore` gives `0 issues.` at
|
||||
exit 0 with the violation still in the tree, and it fails loudly only when
|
||||
other code still references the excluded file.
|
||||
`deps` layers reported `CACHED`; the same build with `--no-cache-filter`
|
||||
removed reported that layer `CACHED`, so the re-execution is attributable to
|
||||
the flag rather than to a changed context; deliberate violations failed the
|
||||
build naming the specific finding and reverted clean; a stage-name typo
|
||||
failed loudly at exit 1; and a Go file excluded via `.dockerignore` reported
|
||||
`0 issues.` at exit 0 with the violation still in the tree. Wall-clock
|
||||
durations vary per host and per run, so they are not recorded here.
|
||||
|
||||
- 2026-08-09 `TestAutoSaveOnSignalRacesTurnLoop` de-flaked at the cause
|
||||
(`fix/autosave-turn-budget-36`, closes #36). The failure text was captured
|
||||
|
||||
Reference in New Issue
Block a user