script/bootstrap installs pinned tools only when missing, so the golangci-lint pin is inert on any machine that already has one #117
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/bootstrapguards its pinnedgo installcalls behind a presence check:missingtests only whether the binary is onPATH, not whether it is the pinned version. So on any machine that already has somegolangci-lint— any version, from any source — bootstrap silently skips the install and the pin does nothing.Why this matters here specifically
This repo moved to golangci-lint v2.12.2 (commit pin
c0d3ddc9cf3faa61a4e378e879ece580256d76e5) with an org-standard v2-schema.golangci.yml. A v1.x linter cannot parse that config at all, and a different v2.x will not necessarily produce the same findings.So the failure modes are:
make lintand gets a config schema error that looks like a broken repo rather than a stale tool.make checkpasses locally, then fails in the Docker build — or, more insidiously, passes in both while a finding CI would have caught is never surfaced.GOLANGCI_LINT_REFin this file updates the Dockerfile-matching comment and the pin, and changes nothing for anyone who has already bootstrapped. The pin exists precisely so local and CI linting agree; this guard defeats that.The
Dockerfileis unaffected — it runsgo installunconditionally in a clean image, which is why local and CI can diverge without anyone noticing.The comment at the top of the file states the intent the code fails to deliver: "golangci-lint and goimports are installed via
go installat the same pinned commits the Dockerfile uses (never 'latest')."Definition of done
script/bootstrapguarantees the pinned versions are what end up installed, regardless of what was onPATHbeforehand.go installat a pinned ref is idempotent and cheap when the module cache is warm, so the simplest correct fix is to drop themissingguard for these two tools and always run the install. If you prefer to keep a guard, it must compare the installed version against the pin, not merely test for presence — and a version check that can be fooled by a differently-built binary is not good enough.missingguard stays forgit,make, andgo, which come from the system package manager and are genuinely presence-checks. Do not remove those.script/bootstrapremains POSIXsh(#!/bin/sh,set -eu, no bashisms) — it runs in minimal alpine containers with no bash — and keeps the$(cd "$(dirname "$0")/.." && pwd -P)root-location idiom.PATH, runscript/bootstrap, and confirm the pinned version is whatgolangci-lint --versionreports afterwards. A code-reading argument is not sufficient — this is a bug about the gap between what the script says and what it does.make checkgreen;TODO.mdupdated in the same commit.The finishing commit's title must end with
(closes #N)referencing this issue.Hard constraints
GOLANGCI_LINT_REFmust stayc0d3ddc9cf3faa61a4e378e879ece580256d76e5(v2.12.2) andGOIMPORTS_REFmust stay009367f5c17a8d4c45a961a3a509277190a9a6f0. This issue is about making the existing pins effective, not about updating them..golangci.yml— it is org-standardised and must never be touched by an agent. Its sha256 must remain021cc83f4e6fc7c31b95b34b846723dfcf20b66b7baeea1dc40406e643346bcb.script/bootstrapand theDockerfileidentical to each other. If you touch one, check the other.go installat a commit ref is fine (the hash is recorded in the module system);curl | shis never acceptable in this repo.Context
Found via cross-repo review — this is a defect in the shared Scripts to Rule Them All template, identified independently by managers on sibling repos, and is now tracked upstream in the
promptsrepo alongside thescript/cibuildcache hole (#115) and two other template defects. Fixing it here does not depend on the upstream fix landing, and the two should be kept consistent.Implemented in #131 (branch
fix/117-bootstrap-pin, commitdb933f3).What changed in
script/bootstrapgolangci-lintandgoimportsare installed unconditionally at their pinned commit refs; themissingguard is gone for those two.go installat a fixed ref is idempotent and cheap with a warm module cache.missingis retained forgit,make, andgo, per DoD item 2.command -vresolves either tool to something other than the directorygo installwrote to. Installing the pin is necessary but not sufficient — a shadowing copy earlier onPATHis whatmake lint/make fmtwould actually execute. It warns rather than fails because the remedy is the operator'sPATH.#!/bin/sh+set -eu, no bashisms,sh -nclean,$(cd "$(dirname "$0")/.." && pwd -P)idiom kept.Pins unchanged and still identical to the
Dockerfile..golangci.ymluntouched, sha256 still021cc83f4e6fc7c31b95b34b846723dfcf20b66b7baeea1dc40406e643346bcb.Empirical verification with a negative control (DoD item 6). Done in an isolated
GOBINfirst onPATH, so no shared tooling on this host was disturbed.golangci-lint --versioninvoked directly on purpose — it is the measurement.GOBIN.golangci-lint --versionreported2.10.1.script/bootstrapagainst thatGOBIN/PATH.golangci-lint --versionreported2.12.2, resolving to the scratchGOBINcopy; its sha2566a8bfa407ebb902a291559f4a8a0dca6421ac96410c4722e32e4c96ea95d51d7is byte-identical to the host's existing pinned v2.12.2 build. Onmainthis step is a no-op and the 2.10.1 binary survives — that is the bug.Idempotency (DoD item 4): second consecutive run exited 0 with the same versions and the same binary hashes.
Shadow warning: with an empty
GOBINandPATHstill resolving both tools elsewhere, the warning fired for both and the script exited 0.make checkgreen (exit 0,0 issues.), run with an isolatedGOLANGCI_LINT_CACHE/TMPDIRper #121; output contained noparallel golangci-lint is runningand no paths outside the worktree.TODO.mdupdated in the same commit.Incidental, not fixed here: running
script/bootstrapalso rewritesgo.mod, droppinggolang.org/x/sync v0.19.0 // indirect, becausego mod downloadwith no arguments updates the main module's requirements. Pre-existing onmainand outside this issue's scope; reverted rather than carried in the commit.