build: run golangci-lint in a pinned container via script/lint (closes #41)
golangci-lint is no longer invoked on the host anywhere in the repo.
Dockerfile.lint pins golangci/golangci-lint:v2.12.2 by digest and runs
the linter as a build step, so a successful build IS a clean lint, and
`make lint` becomes a thin shim over script/lint. This removes the host
linter install that produced a false green here, where a 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 shape:
- Two stages rather than one. A cached `deps` stage holds
`go mod download`, then `FROM deps AS lint` carries the source 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 re-fetch the module cache over the
network on every run.
- No `golangci-lint config verify` step. It resolves its JSON schema
over a live, unpinned HTTPS call: 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. The reason is recorded in a
comment in Dockerfile.lint.
.dockerignore excludes .git only; the lint reads the Go sources,
go.mod/go.sum and .golangci.yml, none of which come from there.
The TODO.md scaffold-exemption note is narrowed rather than dropped:
Dockerfile.lint and script/lint are now permitted and required, while CI
config, REPO_POLICIES.md, an application Dockerfile and any other
script/ entrypoint still are not.
Verified, since a green docker build is the classic false green: two
consecutive script/lint runs on an unchanged tree each showed the
`golangci-lint run` layer executing (9.8s and 7.9s, both "0 issues.")
while the deps layers reported CACHED; a deliberate indent-error-flow
violation failed the build naming that finding and the unused one, and a
revert went clean again. `make check` green.
This commit is contained in:
42
TODO.md
42
TODO.md
@@ -35,6 +35,34 @@ is finished.
|
||||
|
||||
# Completed Steps
|
||||
|
||||
- 2026-08-10 Linting moved into a container
|
||||
(https://git.eeqj.de/sneak/rgoue/issues/41). `golangci-lint` is no longer
|
||||
invoked on the host anywhere in the repo: `Dockerfile.lint` pins
|
||||
`golangci/golangci-lint:v2.12.2` by digest and runs the linter as a build
|
||||
step, so a successful build is a clean lint, and `make lint` is now a shim
|
||||
over `script/lint`. This is what killed the false green seen earlier, where a
|
||||
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.
|
||||
|
||||
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 (11.6s and 9.7s, both `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.
|
||||
|
||||
- 2026-08-09 `TestAutoSaveOnSignalRacesTurnLoop` de-flaked at the cause
|
||||
(`fix/autosave-turn-budget-36`, closes #36). The failure text was captured
|
||||
before anything was changed and it is **not** a data race: the assertion was
|
||||
@@ -853,7 +881,13 @@ is finished.
|
||||
per-game dungeon dimensions instead of the 80x24 constants; open design
|
||||
questions are resize policy, gameplay tuning at larger sizes, and a --classic
|
||||
80x24 mode.
|
||||
2. Note: this repo is exempt from the standard policy scaffold. A minimal dev
|
||||
Makefile (fmt/fmt-check/lint/test/check targets) exists per sneak's
|
||||
2026-07-07 request, but do not add a Dockerfile, CI config, or
|
||||
REPO_POLICIES.md.
|
||||
2. Note: this repo is exempt from the standard policy scaffold, but the
|
||||
exemption is narrower than it was. A minimal dev Makefile
|
||||
(fmt/fmt-check/lint/test/check targets) exists per sneak's 2026-07-07
|
||||
request. `Dockerfile.lint` and `script/lint` are now also permitted, and
|
||||
required: sneak's 2026-08-09 ruling
|
||||
(https://git.eeqj.de/sneak/rgoue/issues/41) is that every repo lints in a
|
||||
container invoked through `script/lint`, and being later and explicit it
|
||||
overrides the 2026-07-07 exemption for those two files only. Still do not
|
||||
add: CI config, `REPO_POLICIES.md`, an application `Dockerfile`, or any other
|
||||
`script/` entrypoint.
|
||||
|
||||
Reference in New Issue
Block a user