operator-sdk generates invalid golangci-lint configuration
Bug Report
What did you do?
After initializing a project and creating an API with operator-sdk, I attempted to run golangcilint-run.
What did you expect to see?
I expected the linter to complete successfully.
What did you see instead? Under which circumstances?
The linter failed immediately with:
$ golangci-lint run
Error: can't load config: unsupported version of the configuration: "" See https://golangci-lint.run/product/migration-guide for migration instructions
Failed executing command with error: can't load config: unsupported version of the configuration: "" See https://golangci-lint.run/product/migration-guide for migration instructions
Adding the required version: "2" to the file leads to new errors:
Error: can't load config: typecheck is not a linter, it cannot be enabled or disabled
Failed executing command with error: can't load config: typecheck is not a linter, it cannot be enabled or disabled
If we remove typecheck, we get:
Error: can't load config: gofmt is a formatter
Failed executing command with error: can't load config: gofmt is a formatter
If we move gofmt and goimports to the formatters section, we get:
Error: unknown linters: 'exportloopref,gosimple', run 'golangci-lint help linters' to see the list of supported linters
Failed executing command with error: unknown linters: 'exportloopref,gosimple', run 'golangci-lint help linters' to see the list of supported linters
If we remove exportloopref and gosimple from the configuration, golangci-lint finally runs, but it then discovers a number of issues with the generated code:
WARN [runner/nolint_filter] Found unknown linters in //nolint directives: golint
cmd/main.go:17:1: package-comments: should have a package comment (revive)
package main
^
internal/controller/suite_test.go:17:1: package-comments: should have a package comment (revive)
package controller
^
internal/controller/suite_test.go:26:2: dot-imports: should not use dot imports (revive)
. "github.com/onsi/ginkgo/v2"
^
internal/controller/widget_controller.go:49:59: unused-parameter: parameter 'req' seems to be unused, consider removing or renaming it as _ (revive)
func (r *WidgetReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
^
internal/controller/widget_controller_test.go:22:2: dot-imports: should not use dot imports (revive)
. "github.com/onsi/ginkgo/v2"
^
internal/controller/widget_controller_test.go:23:2: dot-imports: should not use dot imports (revive)
. "github.com/onsi/gomega"
^
test/utils/utils.go:17:1: package-comments: should have a package comment (revive)
package utils
^
test/utils/utils.go:25:2: ST1001: should not use dot imports (staticcheck)
. "github.com/onsi/ginkgo/v2" //nolint:golint,revive
^
test/utils/utils.go:138:7: QF1004: could use strings.ReplaceAll instead (staticcheck)
wd = strings.Replace(wd, "/test/e2e", "", -1)
^
9 issues:
* revive: 7
* staticcheck: 2
Environment
Operator type:
/language go
Kubernetes cluster type:
OpenShift
$ operator-sdk version
operator-sdk version: "v1.39.2", commit: "f01ea5405979ab9ce7049877f9a0c23927ccb2ec", kubernetes version: "1.31.0", go version: "go1.23.4", GOOS: "linux", GOARCH: "amd64"
$ go version (if language is Go)
go version go1.23.7 linux/amd64
$ kubectl version
Client Version: v1.31.2 Kustomize Version: v5.4.2
Possible Solution
Update the linting configuration and ensure that it does not report errors on the generated code.
Additional context
golangci-lint version:
golangci-lint has version 2.0.1 built with go1.24.1 from e8927ce2 on 2025-03-24T20:34:31Z
Running golangci-lint migrate takes care of most of these issues, although there are still two remaining issues reported by staticcheck:
WARN [runner/nolint_filter] Found unknown linters in //nolint directives: golint
test/utils/utils.go:25:2: ST1001: should not use dot imports (staticcheck)
. "github.com/onsi/ginkgo/v2" //nolint:golint,revive
^
test/utils/utils.go:138:7: QF1004: could use strings.ReplaceAll instead (staticcheck)
wd = strings.Replace(wd, "/test/e2e", "", -1)
^
2 issues:
* staticcheck: 2
Reverting golangci-lint to the latest 1.x version still results in some warnings:
WARN The linter 'exportloopref' is deprecated (since v1.60.2) due to: Since Go1.22 (loopvar) this linter is no longer relevant. Replaced by copyloopvar.
ERRO [linters_context] exportloopref: This linter is fully inactivated: it will not produce any reports.
Hi @larsks operator-sdk generates a linting file based on the version of golangci-lint that is in the projects Makefile. This ends up with a specific version in ./bin local to the project. It can't be expected that operator-sdk generates a future proof file, if golangci-lint moves to v2 API.
Please run make lint instead with the original scaffolded file.
Issues go stale after 90d of inactivity.
Mark the issue as fresh by commenting /remove-lifecycle stale.
Stale issues rot after an additional 30d of inactivity and eventually close.
Exclude this issue from closing by commenting /lifecycle frozen.
If this issue is safe to close now please do so with /close.
/lifecycle stale