docs: name the two required flags, and record .dockerignore as part of the gate

Comments and documentation only; the docker build invocation and its flags
are untouched, and .dockerignore's effective rules are unchanged.

Two prose gaps from review. First, "both flags below must stay" had lost
its anchor: it ended a paragraph naming only --no-cache-filter, --target
was not introduced until the next one, and three flags follow on the
command, so a reader could pick the wrong pair. It now names --target and
--no-cache-filter explicitly.

Second, the list of things the tooling does not check covered the $stage
seam but not .dockerignore, which sits in the same trust boundary and is
the more likely thing to be edited — the first review on this change
actively suggested extending it for build artifacts. Only what reaches the
container is linted, so excluding a Go source there removes it from the
lint with no warning. Verified rather than asserted: a planted violation
plus that one path in .dockerignore yields `0 issues.` at exit 0 with the
violation still in the working tree, while excluding a file other code
still references fails loudly on `undefined:` typecheck errors instead.
The warning is recorded in script/lint alongside the $stage seam and in
.dockerignore itself, where the edit would actually be made.
This commit is contained in:
2026-08-10 13:29:44 +00:00
parent 20cfb47912
commit 3eb9f81fc4
3 changed files with 33 additions and 8 deletions

View File

@@ -1,3 +1,9 @@
# The lint build reads the Go sources, go.mod/go.sum and .golangci.yml; # The lint build reads the Go sources, go.mod/go.sum and .golangci.yml;
# none of that comes out of .git, so keep the build context small. # none of that comes out of .git, so keep the build context small.
#
# This file is part of the lint gate, not housekeeping: only what reaches
# the container gets linted, so excluding a Go source here silently drops
# it from the lint (a self-contained file yields `0 issues.` at exit 0 with
# the violation still in the tree; it fails loudly only if other code still
# references it). Never exclude Go sources, go.mod/go.sum or .golangci.yml.
.git .git

View File

@@ -89,7 +89,12 @@ is finished.
the stage that actually runs `golangci-lint`. `--target` verifies the 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 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 moving the lint step to another stage, or adding a stage after it, would go
unnoticed. 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.
- 2026-08-09 `TestAutoSaveOnSignalRacesTurnLoop` de-flaked at the cause - 2026-08-09 `TestAutoSaveOnSignalRacesTurnLoop` de-flaked at the cause
(`fix/autosave-turn-budget-36`, closes #36). The failure text was captured (`fix/autosave-turn-budget-36`, closes #36). The failure text was captured

View File

@@ -7,8 +7,9 @@
# #
# --no-cache-filter forces the lint stage to re-execute every run, so an # --no-cache-filter forces the lint stage to re-execute every run, so an
# unchanged tree is still actually linted; the deps stage keeps its cache, # unchanged tree is still actually linted; the deps stage keeps its cache,
# so the module download is not repeated. Both flags below must stay: do # so the module download is not repeated. It and --target must both stay,
# not "simplify" either one away. # for the reason in the next paragraph: do not "simplify" either of those
# two away.
# #
# The stage name is written ONCE, in $stage, and passed to both --target # The stage name is written ONCE, in $stage, and passed to both --target
# and --no-cache-filter, so the two flags cannot come to name different # and --no-cache-filter, so the two flags cannot come to name different
@@ -22,12 +23,25 @@
# silent skip, because the one name reaches both flags. # silent skip, because the one name reaches both flags.
# #
# What the tooling does NOT check, and is left to whoever edits this: # What the tooling does NOT check, and is left to whoever edits this:
# $stage must name the stage in Dockerfile.lint that actually runs #
# 1. $stage must name the stage in Dockerfile.lint that actually runs
# golangci-lint. --target verifies that the name exists, not that it is # golangci-lint. --target verifies that the name exists, not that it is
# the right stage, and it stops the build at that stage — so moving the # the right stage, and it stops the build at that stage — so moving the
# lint step into a different stage, or adding a stage after this one, # lint step into a different stage, or adding a stage after this one,
# would not be caught here. Keep this file and Dockerfile.lint in sync. # would not be caught here. Keep this file and Dockerfile.lint in sync.
# #
# 2. .dockerignore decides what reaches the container, and only what
# reaches it gets linted. Excluding a Go file there removes it from the
# lint with no warning: verified by planting a real violation and adding
# just that file's path to .dockerignore, which produced `0 issues.` at
# exit 0 with the violation still sitting in the working tree. It shows
# up only if the rest of the package still references the excluded file,
# in which case the build fails loudly on `undefined:` typecheck errors;
# a self-contained file drops out silently. So .dockerignore is part of
# this gate, not housekeeping — keep it to build inputs the lint does
# not read, and never exclude Go sources, go.mod/go.sum or
# .golangci.yml.
#
# --output=type=cacheonly skips the image export. Nothing consumes the # --output=type=cacheonly skips the image export. Nothing consumes the
# image — the deliverable of this build is an exit code — and exporting it # image — the deliverable of this build is an exit code — and exporting it
# costs seconds per run and leaves a dangling image behind every time. The # costs seconds per run and leaves a dangling image behind every time. The