我這篇就是把那份草稿整理成你可以直接拿去用的版本。原始來源是 golangci-lint FAQ,我不打算把它講得很玄,因為它本來就不是玄學;它只是把 CI 的邊界講清楚而已。
先別幻想它能跟上每個 Go 新版
訂閱 AI 趨勢週報
每週精選模型發布、工具應用與深度分析,直送信箱。不定期,不騷擾。
不會寄垃圾信,隨時可取消。
“Golangci-lint supports Go versions lower or equal to the Go version used to compile it.”
翻譯一下就是:你的 lint binary 不是神,它是拿某個 Go toolchain 編出來的,所以它能支援的 Go 版本有上限。FAQ 還補了一刀,說它的支援策略跟 Go 官方的兩個最新 minor 版本政策一致。也就是說,你如果先把 repo 升到最新 Go,卻沒同步更新 golangci-lint,CI 出怪事不是意外,是你自己在製造版本落差。
# golangci-lint CI policy for Go repos
# Source: https://golangci-lint.run/docs/welcome/faq/
# Related docs: https://golangci-lint.run/ , https://golangci-lint.run/docs/usage/linters/
policy:
versioning:
go: "pin in CI"
golangci-lint: "pin in CI"
rule: "upgrade Go and golangci-lint together"
note: "golangci-lint only supports Go versions <= the Go version used to compile it"
build_gate:
order:
- "go mod tidy"
- "go build ./..."
- "golangci-lint run ./..."
rule: "typecheck errors are build failures, not lint warnings"
legacy_debt:
rule: "do not block delivery on pre-existing issues in main"
enforce_only_on_new_code: true
commands:
branch_ci: "golangci-lint run --new-from-merge-base=main"
commit_ci: "golangci-lint run --new-from-rev=HEAD~1"
diff_filtering:
default: "diff-based new-code lint"
widen_scope_when:
- "refactor hides issues outside changed lines"
- "file-level edits miss relevant warnings"
fallback_command: "golangci-lint run --new-from-merge-base=main --whole-files"
performance:
expectation: "first run is slower because type info is cached"
practice:
- "persist cache locally and in CI when possible"
- "judge speed after warm cache, not cold start"
custom_checks:
rule: "keep one-off checks out of the main gate until they have a clear owner and stable purpose"
preferred_path: "use built-in linters first; add custom linters only when the use case is durable"
ci_statement: |
The build must compile cleanly.
golangci-lint is enforced only on new code.
Legacy issues stay visible but do not block delivery.
Typecheck errors are treated as build failures, not lint warnings.