Skip to content

ci: bump golangci-lint to v2.13.1 to fix panic on Go 1.27 - #1561

Merged
rdimitrov merged 1 commit into
mainfrom
rdimitrov/fix-lint-go127
Aug 20, 2026
Merged

ci: bump golangci-lint to v2.13.1 to fix panic on Go 1.27#1561
rdimitrov merged 1 commit into
mainfrom
rdimitrov/fix-lint-go127

Conversation

@rdimitrov

@rdimitrov rdimitrov commented Aug 20, 2026

Copy link
Copy Markdown
Member

CI is red on main and on every open PR (including the Dependabot PRs #1531, #1552#1554) with:

panic: file requires newer Go version go1.27 (application built with go1.26)
golangci-lint exit with code 2

Cause

actions/setup-go with go-version: 'stable' started resolving to go1.27.0. The pinned golangci-lint v2.11.4 release binary is built with go1.26, and its go/types refuses to typecheck source files declaring a newer language version. Nothing in the failing PRs is at fault.

Fix

Bump to golangci-lint v2.13.1, whose release binaries are built with go1.27, so linting works under stable again.

That bump also pulls in newer linter versions, which surface 57 findings this tree did not have before. Handled as follows:

Linter Count Resolution
goconst 50 39 were repeated literals in _test.go files — goconst started counting those in v2.12.0 (golangci-lint#6480 exposed ignore-tests). Fixture data like "1.0.0" (89 occurrences) is not a missing constant, so goconst.ignore-tests: true. The other 11 were real duplication in production code (OpenAPI tags, the bearer security scheme name, $ref, http/https) and became named constants.
gosec G710 1 True positive, fixed. See below.
staticcheck SA1019 6 Go 1.26 deprecated ecdsa.PublicKey.X/Y and PrivateKey.D. Annotated with the same targeted nolint + rationale already used for ScalarBaseMult in cmd/publisher/auth/common.go.

The open redirect is real

TrailingSlashMiddleware copied the entire *url.URL before rewriting the path. For an absolute-form request URI — legal for a Go HTTP server to parse, e.g. GET http://evil.com/foo/ HTTP/1.1r.URL.Scheme and r.URL.Host are populated, and they were echoed straight back in the Location header. The redirect target is now built from the cleaned path and query alone. The existing path.Clean hardening for GHSA-v8vw-gw5j-w7m6 (protocol-relative //evil.com/) is unchanged.

Also

Switched gomodguardgomodguard_v2; the former is deprecated as of v2.12.0 and was emitting a warning on every run.

Verification

  • golangci-lint v2.13.1 against this tree: 0 issues, no deprecation warnings
  • make validate: all validations passed
  • go build ./... and tests for every touched package pass (DB-backed tests need Postgres; left to CI)

Note on migrating the ecdsa key paths

Moving those six sites to PublicKey.Bytes / ParseUncompressedPublicKey / crypto/ecdh touches key parsing and signature verification. It should be its own reviewed PR rather than riding along on a CI unblock. Happy to open one.

🤖 Generated with Claude Code

`actions/setup-go` with `go-version: 'stable'` now resolves to go1.27.0. The
pinned golangci-lint v2.11.4 release binary is built with go1.26, and its
`go/types` cannot typecheck source declaring a newer language version, so the
lint step panics and reds CI on main and on every open PR:

    panic: file requires newer Go version go1.27 (application built with go1.26)

v2.13.1 is built with go1.27, so it can lint under `stable` again. It also
brings newer linter versions, which surface 57 findings this tree did not have
before. Addressed as follows:

- goconst (50): 39 were repeated literals in _test.go files, which goconst
  started counting in v2.12.0 (golangci-lint#6480 exposed `ignore-tests`).
  Test fixture data like "1.0.0" (89 occurrences) is not a missing constant, so
  set `goconst.ignore-tests: true`. The remaining 11 were real duplication in
  production code: OpenAPI operation tags and the bearer security scheme name
  repeated across handler registrations, plus "$ref" and "http"/"https". Those
  became named constants.

- gosec G710 open redirect (1): a true positive. TrailingSlashMiddleware copied
  the whole *url.URL, so an absolute-form request URI ("GET http://evil.com/foo/
  HTTP/1.1") had its scheme and host echoed back in the Location header. Build
  the redirect target from the cleaned path and query alone. The existing
  path.Clean hardening for GHSA-v8vw-gw5j-w7m6 is preserved.

- staticcheck SA1019 (6): Go 1.26 deprecated the ecdsa.PublicKey.X/Y and
  PrivateKey.D fields. Annotated with the same targeted nolint and rationale
  already used for ScalarBaseMult in cmd/publisher/auth/common.go; migrating
  these key paths to PublicKey.Bytes/crypto/ecdh deserves its own PR.

Also switch gomodguard to gomodguard_v2, deprecated in v2.12.0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@rdimitrov
rdimitrov force-pushed the rdimitrov/fix-lint-go127 branch from f101371 to 864c519 Compare August 20, 2026 20:03
@rdimitrov rdimitrov changed the title ci: pin lint job Go to go.mod to fix golangci-lint panic on Go 1.27 ci: bump golangci-lint to v2.13.1 to fix panic on Go 1.27 Aug 20, 2026
@rdimitrov
rdimitrov merged commit 8759d9d into main Aug 20, 2026
6 checks passed
@rdimitrov
rdimitrov deleted the rdimitrov/fix-lint-go127 branch August 20, 2026 21:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant