From 5cfd14c95a1b2157bdde2c8d8c1ccb03058f42df Mon Sep 17 00:00:00 2001 From: Min Huang <70873102+min0625@users.noreply.github.com> Date: Fri, 28 Aug 2026 15:45:43 +0000 Subject: [PATCH] ci: upgrade golangci-lint to 2.13.1, rework lint config Migrate `gofumpt.extra-rules` to the 2.13 `extra` block -- it is a split, not a rename, so each sub-rule is named explicitly. Drop the linters now covered by others (gci/gofmt by gofumpt+goimports, copyloopvar/intrange by modernize, whitespace by wsl_v5) plus dupword and goheader, whose value does not carry for this repo. Lift both issue caps and turn off uniq-by-line so a CI run reports every finding instead of one per line. Add gomodguard_v2 with a deprecated-module blocklist and local-replace-directives, which catches a `replace => ../local` that would break the tagged goreleaser build. Azure track 1 goes in that list rather than in depguard: depguard matches raw string prefixes, so a rule naming the module root would also block the track 2 modules under sdk/, and its allow list cannot carve them back out. Extend govet with the non-default analyzers (deepequalerrors, nilness, reflectvaluecompare, sortslice, unusedwrite); `inline` is left off the list because it is enabled by default. Sync the pinned version in AGENTS.md -- 2.12.2 rejects this config outright -- and document the whole-files + --new-from-rev ratchet. Co-Authored-By: Claude Opus 5 --- .golangci.yaml | 70 +++++++++++++++++++++++++++++++------------------- AGENTS.md | 7 ++++- mise.toml | 2 +- 3 files changed, 50 insertions(+), 29 deletions(-) diff --git a/.golangci.yaml b/.golangci.yaml index 48d94da..840d68f 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -1,31 +1,27 @@ # https://golangci-lint.run/docs/configuration/file/ version: "2" -run: - timeout: 5m - issues: whole-files: true - max-same-issues: 50 -severity: - default: error + max-same-issues: 0 # 0 = unlimited; default 3 + max-issues-per-linter: 0 # 0 = unlimited; default 50 + + uniq-by-line: false # default true hides other linters' findings on the same line formatters: enable: - - gci - - gofmt + # goimports rides along with gofumpt because it alone drops unused imports. - gofumpt - goimports - golines settings: - gofmt: - rewrite-rules: - - pattern: "interface{}" - replacement: "any" gofumpt: - extra-rules: true + extra: + group-params: true + clothe-returns: true + balance-calls: true golines: max-len: 120 @@ -42,9 +38,7 @@ linters: # Additional - bodyclose - canonicalheader - - copyloopvar - depguard - - dupword - durationcheck - errchkjson - errname @@ -55,11 +49,9 @@ linters: - gocognit - goconst - gocritic - - goheader - gomodguard_v2 - goprintffuncname - gosec - - intrange - loggercheck - mirror - misspell @@ -90,17 +82,20 @@ linters: - usestdlibvars - usetesting - wastedassign - - whitespace - wsl_v5 settings: govet: enable: + - deepequalerrors - nilness + - reflectvaluecompare + - sortslice + - unusedwrite - modernize: - disable: - - omitzero + nolintlint: + require-specific: true + require-explanation: true depguard: rules: @@ -108,12 +103,33 @@ linters: deny: - pkg: github.com/pkg/errors desc: Should be replaced by standard lib errors package - - pkg: golang.org/x/exp/slices - desc: Should be replaced by standard lib slices package - - pkg: github.com/go-resty/resty$ - desc: Use github.com/go-resty/resty/v2 instead - - pkg: github.com/aws/smithy-go/ptr$ - desc: Use github.com/aws/aws-sdk-go-v2/aws instead + + gomodguard_v2: + # A local `replace` that reaches main breaks the tagged release build. + # Only sees directly imported modules; an indirect dep's replace slips through. + local-replace-directives: true + + # Bar for an entry: archived or known-vulnerable, AND still reached for + # directly today because old tutorials point there. + blocked: + - module: github.com/Azure/azure-sdk-for-go + reason: Track 1 (services/, storage/, profiles/) retired 2023-09-30; use the sdk/ modules (track 2) + - module: github.com/aws/aws-sdk-go + recommendations: + - github.com/aws/aws-sdk-go-v2 + reason: End-of-support since 2025-07-31; no further updates, including security fixes + - module: github.com/dgrijalva/jwt-go + recommendations: + - github.com/golang-jwt/jwt/v5 + reason: Unmaintained; golang-jwt is the community continuation + - module: github.com/golang/mock + recommendations: + - go.uber.org/mock + reason: Archived upstream; go.uber.org/mock is the maintained fork + - module: github.com/satori/go.uuid + recommendations: + - github.com/google/uuid + reason: Unmaintained; on Go 1.27+ prefer the stdlib uuid package exclusions: rules: diff --git a/AGENTS.md b/AGENTS.md index 3cf55e5..f44cef5 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -28,7 +28,7 @@ make check-tidy # verify go.mod/go.sum are tidy make release-snapshot # goreleaser release --snapshot --clean (test release locally) ``` -Tool versions are pinned in [mise.toml](./mise.toml) (Go 1.26.4, golangci-lint 2.12.2, goreleaser 2.16.0, prek 0.4.6). +Tool versions are pinned in [mise.toml](./mise.toml) (Go 1.26.4, golangci-lint 2.13.1, goreleaser 2.16.0, prek 0.4.6). Run `mise install` to set up the exact toolchain. [.pre-commit-config.yaml](./.pre-commit-config.yaml) is the single source of truth for what gets checked: `prek` runs it on `git commit` (staged files), and `make check` runs the same hooks over **all** tracked files, which is what CI runs. `check-tidy`, @@ -107,6 +107,11 @@ bin/mint # compiled binary (gitignored) `check-rev` guard) — `golangci-lint` itself only warns and exits 0, which would let CI pass having linted nothing. The pre-commit hook already runs lint on every commit, so running it by hand is only needed to re-check a different rev. +- Lint config changes do not require fixing the whole codebase. `whole-files: true` + + `--new-from-rev` is a ratchet: a PR fixes the lint of the files it touches, and untouched + files carry their debt until someone edits them. After changing `.golangci.yaml`, run + `golangci-lint run ./...` once (no `--new-from-rev`) to see how much debt the change adds + repo-wide — read the number, don't fix it. - **Release workflow** — push a tag matching `v*.*.*` to automatically trigger GoReleaser CI; creates GitHub Release with multi-platform binaries. - **Local snapshot testing** — run `goreleaser release --snapshot --clean` to validate build configuration before publishing. diff --git a/mise.toml b/mise.toml index 45f9281..a5df3db 100644 --- a/mise.toml +++ b/mise.toml @@ -1,5 +1,5 @@ [tools] go = "1.26.4" -golangci-lint = "2.12.2" +golangci-lint = "2.13.1" goreleaser = "2.16.0" prek = "0.4.6"