script/bootstrap installs golangci-lint unpinned, so local lint diverges from CI #45
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?
From the repo-standards audit. Present on
mainand the pending lint branch.Divergence
Policy, described in its own text as the single most important rule in the document:
> ALL external references must be pinned by cryptographic hash. ... Version tags are server-mutable and therefore remote code execution vulnerabilities. ... never
curl | bashto install tools ... download a specific release archive from GitHub, verify its hash ... There are zero exceptions to this rule.script/bootstrap:142-144:No version, no hash. On apt this becomes
apt-get install -y golangci-lint. The comment directly above these lines already states the correct approach — download a specific release archive and verify withverify_sha256, nevercurl | sh— and the code does not do it. Theverify_sha256helper already exists in the script and is unused for this path.Beyond the pinning rule this is a correctness problem, and a live one given PR #29: a developer's
make lintruns whatever golangci-lint version their distro packages against a config written for v2.12.2. Older versions will not recognize the newer linters and will either error or silently skip them, so local runs and CI disagree about whether the tree is clean. TheDockerfilecorrectly pins v2.12.2 by digest;script/bootstrapdoes not match it.In fairness: the canonical org
script/bootstraphas the same unpinnedpkg_installshape, so this is inherited from the template rather than introduced here. Worth raising upstream against thepromptsrepo as well.Definition of done
script/bootstrapinstalls golangci-lint at a pinned version matching theDockerfile(v2.12.2), from a release archive verified against a hardcoded sha256 via the existingverify_sha256helper.script/bootstrapwith the correct version already installed does not re-download.PATHat a different version, the script says so rather than silently accepting it — a mismatched linter is precisely the failure this is fixing.set -eu, no bashisms.make checkgreen after a freshscript/bootstraprun.TODO.mdupdated in the same commit.Implementation requirements
curl | shthe upstream install script, and do not use the--versionconvenience installer. Download the archive, verify, extract, install.Implementation guidance, from a cross-repo clarification on what "pinned by hash" means for each install mechanism. This narrows the approach and removes a wrong turn, so read it before starting.
The two mechanisms are pinned differently, and this repo needs both.
FROM golangci/golangci-lint:v2.12.2@sha256:5cceeef04e53efe1470638d4b4b4f5ceefd574955ab3941b2d9a68a8c9ad5240, with the version-and-date comment above it. Nothing to do there. If anyone suggests adding a git commit SHA to that line, it is redundant — a Docker digest already pins the exact bytes, and the commit SHA does not participate in what Docker resolves.script/bootstrapinstalls a Go tool onto a developer's machine, which is a different mechanism with a different correct answer. Where the install goes throughgo install, the pin is the upstream git commit, and for golangci-lint v2.12.2 that isc0d3ddc9cf3faa61a4e378e879ece580256d76e5. That form is what this issue needs.So the fix has two viable shapes, and the choice is worth making deliberately rather than by whichever is easier:
go installpinned to the commit —go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@c0d3ddc9cf3faa61a4e378e879ece580256d76e5. Go verifies the module againstgo.sum/GONOSUMDB and the module proxy's transparency log, so this is genuinely content-pinned. It needs a Go toolchain present, whichscript/bootstrapalready guarantees since it installs Go first. It is also platform-agnostic, which removes the per-OS/arch hash table the issue body anticipated.verify_sha256— as the issue body originally described. Still valid, but it needs a hash per platform and more script surface.Option 1 is the better fit here and I would take it unless something blocks it: it is fewer moving parts, it reuses machinery the script already has, it sidesteps maintaining a platform hash table, and it removes the
pkg_installpath entirely rather than working around it. Report on this issue if you hit a reason it does not work.Whichever is chosen, the rest of the definition of done in the issue body stands unchanged — in particular that the version appears exactly once, that a pre-existing golangci-lint at a different version is reported rather than silently accepted, and that the installed version matches the Dockerfile's v2.12.2. The mismatch between a developer's distro-packaged linter and the pinned CI one is the actual bug being fixed here; the pinning-policy compliance is the secondary benefit.
Worth restating the sequencing from the issue body: this lands after PR #29, so the pinned version matches what actually shipped.
Closing as superseded. The owner ruling captured in #55 moves every lint run into a Docker container invoked through
script/lint, and explicitly removes the golangci-lint install fromscript/bootstrap— so there is no longer a host linter that can diverge from CI, which was this issue's entire subject. Nothing here is dropped: the divergence is eliminated rather than pinned.The Dockerfile lint-stage digest pin noted above is already correct and stays.