Isolate golangci-lint cache per worktree to stop cross-worktree contamination#5925
Open
janniklasrose wants to merge 1 commit into
Open
Isolate golangci-lint cache per worktree to stop cross-worktree contamination#5925janniklasrose wants to merge 1 commit into
janniklasrose wants to merge 1 commit into
Conversation
…mination golangci-lint keys its results cache on file *contents* but stores each cached issue's *absolute* path. Two worktrees with byte-identical packages (the near-static tools/ module is the usual culprit) get a cross-worktree cache hit, so the second inherits the first's absolute paths. The //nolint processor then re-opens those paths to apply suppressions; when the other worktree has been deleted the open fails, so suppressed issues (e.g. dupword) leak through as phantom failures pointing at a gone path, plus a wall of "no such file or directory" warnings. The content-addressable cache keys added in v2.12.0 only fixed the concurrent case (both worktrees live). The deleted-worktree case still reproduces on the pinned v2.12.2. Rooting GOLANGCI_LINT_CACHE under the gitignored per-worktree .task/ makes contamination structurally impossible. CI is unaffected: it runs a single checkout and never persists this directory (setup-go caches only the Go build cache). Co-authored-by: Isaac
Contributor
Waiting for approvalBased on git history, these people are best suited to review:
Eligible reviewers: Suggestions based on git history. See OWNERS for ownership rules. |
Collaborator
Integration test reportCommit: f1f1ad9
8 interesting tests: 4 SKIP, 3 RECOVERED, 1 flaky
Top 10 slowest tests (at least 2 minutes):
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Running lint (and thus
./task test's lint step / dev loop) from a worktree under~/pub/cli.worktrees/*intermittently fails with phantom lint issues pointing at file paths in other worktrees — including deleted ones (failed to parse file … no such file or directory).golangci-lint keys its results cache on file contents but stores each cached issue's absolute path. Two worktrees with byte-identical packages (the near-static
tools/module is the usual culprit) get a cross-worktree cache hit in the machine-global~/Library/Caches/golangci-lint, so the second worktree inherits the first's absolute paths. The//nolintpost-processor then re-opens those paths to apply suppressions; when the other worktree has been deleted the open fails, so suppressed issues (e.g.dupword) leak through as phantom failures.The content-addressable cache keys added in golangci-lint v2.12.0 (which the Taskfile comment credited) only fixed the concurrent case where both worktrees are live. The deleted-worktree case still reproduces on the pinned v2.12.2 — verified with throwaway worktrees: lint
tools/in worktree A → delete A → lint identicaltools/in worktree B ⇒ 3 phantomdupwordfailures before this change, 0 after.Fix
Set
GOLANGCI_LINT_CACHEto a per-worktree path ({{.ROOT_DIR}}/.task/golangci-lint) in a top-levelenv:block, so the cache lives under each worktree's already-gitignored.task/. No two worktrees can share it, making contamination structurally impossible.run,fmt, lintdiff) via the top-levelenv:.go-buildcache stays shared).lintjob runs a single clean checkout and never persists this directory (setup-gocaches only the Go build cache, keyed ongo.sum+.golangci.yaml).Testing
Reproduced the failure and confirmed the fix end-to-end using disposable detached worktrees (create A →
./task lint-go-tools→ delete A → lint identical B): phantomdupwordfailures before,0 issuesafter, with B using its own.task/golangci-lint.This pull request and its description were written by Isaac.