REPO_POLICIES requires the form # image:vX.Y.Z, YYYY-MM-DD above every hash-pinned reference. The (Debian-based) parenthetical breaks that form, and worse, it implies the v2.12.2 bump changed the base distribution. It did not — the reviewer ran both the old and new digests and confirmed v2.12.1 was Debian trixie too. A comment that explains a change that never happened is worse than no comment.
2. The pin form is inconsistent with its siblings.Dockerfile:3 uses FROM golangci/golangci-lint:v2.12.2@sha256:..., while the builder and runtime stages both use the bare FROM image@sha256:... form, which is also what the policy template shows. Security-neutral — the digest governs either way — but three FROM lines in one file should not use two conventions.
Dockerfile:3 uses the bare FROM golangci/golangci-lint@sha256:... form, matching the other two stages and the policy template. The digest is unchanged: sha256:5cceeef04e53efe1470638d4b4b4f5ceefd574955ab3941b2d9a68a8c9ad5240.
The version/date comments above the golang and alpine pins are checked against the same required format while in there.
make check green and make docker succeeds, still building the lint stage from the same digest.
Two cosmetic-but-real defects on the lint stage, raised as non-blocking findings during the review of PR #2.
**1. The comment says something untrue.** `Dockerfile:2` reads:
# golangci/golangci-lint:v2.12.2 (Debian-based), 2026-08-07
REPO_POLICIES requires the form `# image:vX.Y.Z, YYYY-MM-DD` above every hash-pinned reference. The `(Debian-based)` parenthetical breaks that form, and worse, it implies the v2.12.2 bump changed the base distribution. It did not — the reviewer ran both the old and new digests and confirmed v2.12.1 was Debian trixie too. A comment that explains a change that never happened is worse than no comment.
**2. The pin form is inconsistent with its siblings.** `Dockerfile:3` uses `FROM golangci/golangci-lint:v2.12.2@sha256:...`, while the builder and runtime stages both use the bare `FROM image@sha256:...` form, which is also what the policy template shows. Security-neutral — the digest governs either way — but three `FROM` lines in one file should not use two conventions.
## Definition of done
1. `Dockerfile:2` reads exactly `# golangci/golangci-lint:v2.12.2, 2026-08-07`.
2. `Dockerfile:3` uses the bare `FROM golangci/golangci-lint@sha256:...` form, matching the other two stages and the policy template. The digest is unchanged: `sha256:5cceeef04e53efe1470638d4b4b4f5ceefd574955ab3941b2d9a68a8c9ad5240`.
3. The version/date comments above the `golang` and `alpine` pins are checked against the same required format while in there.
4. `make check` green and `make docker` succeeds, still building the lint stage from the same digest.
clawbot
added this to the 1.0.0 milestone 2026-08-09 03:58:25 +02:00
Still live after #46 (d43c1d3),
and now doubled: Dockerfile.lint carries the same (Debian-based) parenthetical and the same tag-plus-digest FROM
form. Both files are in scope.
Implementation requirements:
Dockerfile:2 and the corresponding comment in Dockerfile.lint
read exactly # golangci/golangci-lint:v2.12.2, 2026-08-07.
Both FROM lines use the bare FROM golangci/golangci-lint@sha256:...
form. Digest unchanged: sha256:5cceeef04e53efe1470638d4b4b4f5ceefd574955ab3941b2d9a68a8c9ad5240.
Check the golang and alpine pin comments against the same format
while in there.
The trap: script/verify-lint-image-pin exists to keep those two FROM lines identical and parses them to do it. Dropping the tag
changes what it parses. Read it first, keep it working, and prove it
still fails on a tag-only and a digest-only disagreement after the
change — a guard that silently stops comparing is worse than the
inconsistency being fixed.
make check green and make docker still building both images from
the same digest.
Still live after https://git.eeqj.de/sneak/sfdupes/issues/46 (`d43c1d3`),
and now doubled: `Dockerfile.lint` carries the same
`(Debian-based)` parenthetical and the same tag-plus-digest `FROM`
form. Both files are in scope.
Implementation requirements:
- `Dockerfile:2` and the corresponding comment in `Dockerfile.lint`
read exactly `# golangci/golangci-lint:v2.12.2, 2026-08-07`.
- Both `FROM` lines use the bare `FROM golangci/golangci-lint@sha256:...`
form. Digest unchanged:
`sha256:5cceeef04e53efe1470638d4b4b4f5ceefd574955ab3941b2d9a68a8c9ad5240`.
- Check the `golang` and `alpine` pin comments against the same format
while in there.
The trap: `script/verify-lint-image-pin` exists to keep those two
`FROM` lines identical and parses them to do it. Dropping the tag
changes what it parses. Read it first, keep it working, and prove it
still fails on a tag-only and a digest-only disagreement after the
change — a guard that silently stops comparing is worse than the
inconsistency being fixed.
`make check` green and `make docker` still building both images from
the same digest.
Both files now read # golangci/golangci-lint:v2.12.2, 2026-08-07 over FROM golangci/golangci-lint@sha256:5cceeef04e53efe1470638d4b4b4f5ceefd574955ab3941b2d9a68a8c9ad5240.
Digest unchanged. The golang and alpine pin comments already matched
the required form; untouched.
Guard (script/verify-lint-image-pin): its awk matches golangci/golangci-lint[:@], so the tagless reference still parses — no
logic change was needed. Evidence, all after the change:
agreeing pins: exits 0 and prints the shared reference; both builds
ran the gate live, not cached (make check, Dockerfile.lint: gate lint-image-pin ... agree on ...@sha256:5cce...; make docker,
lint stage [7/9], same output).
digest-only disagreement: exits 1 with both refs printed, and fails
the build — perturbing Dockerfile to a zero digest aborted docker build -f Dockerfile.lint . at [6/8] gate lint-image-pin with exit code: 1. Perturbation reverted.
tag-only disagreement: this case no longer exists, since neither
reference carries a tag. Tag drift is still caught: a tag
reintroduced on one side only is a plain string mismatch and fails
(verified against fixtures), as do two differing tags if tags ever
return.
no vacuous pass: an unparseable reference is a hard failure, not an
empty-vs-empty compare. Mangling the image name gives expected exactly one golangci/golangci-lint FROM reference, found 0
and exit 1, whether one file or both are mangled.
One deviation, disclosed rather than folded in: the guard's advice line
said "bump both FROM lines together, tag and digest", which is now
inaccurate; it reads "bump both FROM lines together so ...". Message
text only, no logic.
Verification: make check green with the linter demonstrably executing
(gate lint 36.2s, 0 issues., not CACHED; tests ok sneak.berlin/go/sfdupes 2.427s). make docker green, both images
built from that same digest, lint gates 35.7s, builder gate test 32.3s.
Not run: any behaviour, ordering or gate change; nothing outside the two
Dockerfiles, that one message line, and the TODO.md entry.
Done on `next` as `337b319`.
Both files now read `# golangci/golangci-lint:v2.12.2, 2026-08-07` over
`FROM golangci/golangci-lint@sha256:5cceeef04e53efe1470638d4b4b4f5ceefd574955ab3941b2d9a68a8c9ad5240`.
Digest unchanged. The `golang` and `alpine` pin comments already matched
the required form; untouched.
Guard (`script/verify-lint-image-pin`): its awk matches
`golangci/golangci-lint[:@]`, so the tagless reference still parses — no
logic change was needed. Evidence, all after the change:
- agreeing pins: exits 0 and prints the shared reference; both builds
ran the gate live, not cached (`make check`, `Dockerfile.lint`:
`gate lint-image-pin` ... `agree on ...@sha256:5cce...`; `make docker`,
lint stage `[7/9]`, same output).
- digest-only disagreement: exits 1 with both refs printed, and fails
the build — perturbing `Dockerfile` to a zero digest aborted
`docker build -f Dockerfile.lint .` at `[6/8]`
`gate lint-image-pin` with `exit code: 1`. Perturbation reverted.
- tag-only disagreement: this case no longer exists, since neither
reference carries a tag. Tag drift is still caught: a tag
reintroduced on one side only is a plain string mismatch and fails
(verified against fixtures), as do two differing tags if tags ever
return.
- no vacuous pass: an unparseable reference is a hard failure, not an
empty-vs-empty compare. Mangling the image name gives
`expected exactly one golangci/golangci-lint FROM reference, found 0`
and exit 1, whether one file or both are mangled.
One deviation, disclosed rather than folded in: the guard's advice line
said "bump both FROM lines together, tag and digest", which is now
inaccurate; it reads "bump both FROM lines together so ...". Message
text only, no logic.
Verification: `make check` green with the linter demonstrably executing
(`gate lint` 36.2s, `0 issues.`, not `CACHED`; tests
`ok sneak.berlin/go/sfdupes 2.427s`). `make docker` green, both images
built from that same digest, lint gates 35.7s, builder `gate test` 32.3s.
Not run: any behaviour, ordering or gate change; nothing outside the two
Dockerfiles, that one message line, and the `TODO.md` entry.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Two cosmetic-but-real defects on the lint stage, raised as non-blocking findings during the review of PR #2.
1. The comment says something untrue.
Dockerfile:2reads:REPO_POLICIES requires the form
# image:vX.Y.Z, YYYY-MM-DDabove every hash-pinned reference. The(Debian-based)parenthetical breaks that form, and worse, it implies the v2.12.2 bump changed the base distribution. It did not — the reviewer ran both the old and new digests and confirmed v2.12.1 was Debian trixie too. A comment that explains a change that never happened is worse than no comment.2. The pin form is inconsistent with its siblings.
Dockerfile:3usesFROM golangci/golangci-lint:v2.12.2@sha256:..., while the builder and runtime stages both use the bareFROM image@sha256:...form, which is also what the policy template shows. Security-neutral — the digest governs either way — but threeFROMlines in one file should not use two conventions.Definition of done
Dockerfile:2reads exactly# golangci/golangci-lint:v2.12.2, 2026-08-07.Dockerfile:3uses the bareFROM golangci/golangci-lint@sha256:...form, matching the other two stages and the policy template. The digest is unchanged:sha256:5cceeef04e53efe1470638d4b4b4f5ceefd574955ab3941b2d9a68a8c9ad5240.golangandalpinepins are checked against the same required format while in there.make checkgreen andmake dockersucceeds, still building the lint stage from the same digest.Still live after #46 (
d43c1d3),and now doubled:
Dockerfile.lintcarries the same(Debian-based)parenthetical and the same tag-plus-digestFROMform. Both files are in scope.
Implementation requirements:
Dockerfile:2and the corresponding comment inDockerfile.lintread exactly
# golangci/golangci-lint:v2.12.2, 2026-08-07.FROMlines use the bareFROM golangci/golangci-lint@sha256:...form. Digest unchanged:
sha256:5cceeef04e53efe1470638d4b4b4f5ceefd574955ab3941b2d9a68a8c9ad5240.golangandalpinepin comments against the same formatwhile in there.
The trap:
script/verify-lint-image-pinexists to keep those twoFROMlines identical and parses them to do it. Dropping the tagchanges what it parses. Read it first, keep it working, and prove it
still fails on a tag-only and a digest-only disagreement after the
change — a guard that silently stops comparing is worse than the
inconsistency being fixed.
make checkgreen andmake dockerstill building both images fromthe same digest.
Done on
nextas337b319.Both files now read
# golangci/golangci-lint:v2.12.2, 2026-08-07overFROM golangci/golangci-lint@sha256:5cceeef04e53efe1470638d4b4b4f5ceefd574955ab3941b2d9a68a8c9ad5240.Digest unchanged. The
golangandalpinepin comments already matchedthe required form; untouched.
Guard (
script/verify-lint-image-pin): its awk matchesgolangci/golangci-lint[:@], so the tagless reference still parses — nologic change was needed. Evidence, all after the change:
ran the gate live, not cached (
make check,Dockerfile.lint:gate lint-image-pin...agree on ...@sha256:5cce...;make docker,lint stage
[7/9], same output).the build — perturbing
Dockerfileto a zero digest aborteddocker build -f Dockerfile.lint .at[6/8]gate lint-image-pinwithexit code: 1. Perturbation reverted.reference carries a tag. Tag drift is still caught: a tag
reintroduced on one side only is a plain string mismatch and fails
(verified against fixtures), as do two differing tags if tags ever
return.
empty-vs-empty compare. Mangling the image name gives
expected exactly one golangci/golangci-lint FROM reference, found 0and exit 1, whether one file or both are mangled.
One deviation, disclosed rather than folded in: the guard's advice line
said "bump both FROM lines together, tag and digest", which is now
inaccurate; it reads "bump both FROM lines together so ...". Message
text only, no logic.
Verification:
make checkgreen with the linter demonstrably executing(
gate lint36.2s,0 issues., notCACHED; testsok sneak.berlin/go/sfdupes 2.427s).make dockergreen, both imagesbuilt from that same digest, lint gates 35.7s, builder
gate test32.3s.Not run: any behaviour, ordering or gate change; nothing outside the two
Dockerfiles, that one message line, and the
TODO.mdentry.clawbot referenced this issue2026-08-10 16:07:56 +02:00
clawbot referenced this issue2026-09-04 11:36:06 +02:00
clawbot referenced this issue2026-09-04 11:51:02 +02:00
clawbot referenced this issue2026-09-04 11:53:24 +02:00
clawbot referenced this issue2026-09-04 12:07:25 +02:00