script/bootstrap never checks the golangci-lint version, so the pin is inert #24
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
script/bootstrap:74installs the pinned linter only when the command is absent:missing()is! command -v "$1". So on any machine that already has somegolangci-lintonPATH,GOLANGCI_LINT_REFis never consulted and the pin does nothing. Bumping the version inscript/bootstrap— which is exactly what #3 just did — has no effect on such a machine, forever.This is not hypothetical. Reproduced on the manager host immediately after #3 merged:
So
make checkreported green while running a linter two minor versions behind the pin, against a config written for a newer one. The Docker lint stage uses the digest-pinned image and is unaffected, which means local and CI can disagree silently — the worst possible failure mode for a gate, because the disagreement only shows up after a push.Pre-existing since
3abeacf; surfaced by the independent review of PR #2.Definition of done
script/bootstrapcompares the installed version against the pin and reinstalls when it differs, rather than testing only for presence. Parsegolangci-lint --versionand match the pinned version exactly.script/bootstrapinstalls (git,make,go); document deliberately unpinned system tools rather than silently leaving them.script/bootstrapon a host with a wrong-versiongolangci-lintupgrades it, and a second run is a no-op.make checkandmake dockergreen, and a localmake lintuses the same linter version as the Dockerfile lint stage.Implementation plan (branch
bootstrap-version-check, frommainat076d822):Split the pin into a single source of truth in
script/bootstrap:GOLANGCI_LINT_VERSION="2.12.2"(no leadingv, matching what thebinary prints), with
GOLANGCI_LINT_REFderived from it asgithub.com/golangci/golangci-lint/v2/cmd/golangci-lint@v$GOLANGCI_LINT_VERSION.A future bump then edits exactly one string, and the install ref and
the comparison value cannot drift apart (DoD 2).
Add a
golangci_lint_version()helper that returns the installedversion or the empty string when the tool is absent. It returns
early if
command -v golangci-lintfails (so a missing binary isjust "no version" rather than an error under
set -eu), otherwise itparses
golangci-lint --versionwithawk, taking the field afterthe literal word
versionand stripping an optional leadingv.That handles both shapes seen in the wild: this host's
golangci-lint has version 2.10.1 built with go1.26.5 from (unknown, modified: ?, mod sum: "...") on (unknown)and the pinned image'sversion-plus-commit line.
Replace the presence test with a version test (DoD 1):
which covers absent, older and newer alike, and is a no-op on the
second run (DoD 4). It prints what it found and what it wants before
installing, so the upgrade is visible in the bootstrap output.
Audit the other installs (DoD 3):
git,makeandgocome fromthe host package manager and are deliberately unpinned — the repo
pins no system toolchain versions and
go.modgoverns the languageversion. Rather than leave that ambiguous next to a tool that now
is version-checked, add a comment above the three
missingcallsstating that presence-only is intentional for system packages, and a
comment on the linter block stating why it is different (a stale
linter silently disagrees with the digest-pinned Dockerfile lint
stage, which is exactly the failure this issue is about). No system
package gets pinned.
POSIX
shthroughout (#!/bin/sh,set -eu, no bashisms) since Alpinehas no bash; existing structure and comment style preserved.
Verification (DoD 4 and 5): this host currently has v2.10.1 against the
v2.12.2 pin, so it is a live reproduction — run
script/bootstrapandshow the upgrade, run it again and show the no-op, report
golangci-lint --versionbefore and after, then runmake checkandmake dockerand confirm the local linter now matches the Dockerfilelint stage. If v2.12.2 surfaces findings on
mainthat v2.10.1 washiding, those get reported rather than fixed here — out of scope for
this issue.
TODO.mdgets a Completed Steps entry in the same commit.