-
Notifications
You must be signed in to change notification settings - Fork 40.6k
golangci-lint v2 #131477
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
golangci-lint v2 #131477
Conversation
@pohly: GitHub didn't allow me to request PR reviews from the following users: mmorel-35, ldez. Note that only kubernetes members and repo collaborators can review this PR, and authors cannot review their own PRs. In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
@@ -65,7 +65,7 @@ func Convert_v1_JSON_To_apiextensions_JSON(in *JSON, out *apiextensions.JSON, s | |||
} | |||
*out = i | |||
} else { | |||
out = nil | |||
*out = nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a really subtle one, we'll need to tag in API reviewers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/assign @liggitt
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without this:
ERROR: staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/conversion.go:68:3: ineffectual assignment to out (ineffassign)
ERROR: out = nil
ERROR: ^
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
This change is correct, the linter was correct to flag the old code.
-
This change is also safe.
out
must be a non-nil pointer for conversion to work, and in all call sites, a non-nilout
pointer is passed. -
This change is also ultimately a no-op for existing callers because in all call sites, a nil
in
parameter is never passed.- This is either because the source is not a pointer, so is always non-nil:
Line 766 in c064ed8
if err := Convert_v1_JSON_To_apiextensions_JSON(&(*in)[i], &(*out)[i], s); err != nil { - Or the source is a pointer but the nil case is handled by directly assigning nil to the destination rather than calling
Convert_v1_JSON_To_apiextensions_JSON
:Lines 742 to 750 in c064ed8
if in.Default != nil { in, out := &in.Default, &out.Default *out = new(apiextensions.JSON) if err := Convert_v1_JSON_To_apiextensions_JSON(*in, *out, s); err != nil { return err } } else { out.Default = nil } Lines 898 to 906 in c064ed8
if in.Example != nil { in, out := &in.Example, &out.Example *out = new(apiextensions.JSON) if err := Convert_v1_JSON_To_apiextensions_JSON(*in, *out, s); err != nil { return err } } else { out.Example = nil }
- This is either because the source is not a pointer, so is always non-nil:
hack/tools/go.mod
Outdated
@@ -7,69 +7,77 @@ godebug default=go1.24 | |||
require ( | |||
github.com/aojea/sloppy-netparser v0.0.0-20210819225411-1b3bd8b3b975 | |||
github.com/cespare/prettybench v0.0.0-20150116022406-03b8cfe5406c | |||
github.com/golangci/golangci-lint v1.64.5 | |||
github.com/golangci/golangci-lint/v2 v2.1.5 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
starting to think about moving tools into seperate modules, so they behave closer to if you just go install
ed them and don't conflate dep versions, there are some tradeoffs (sharing deps improves build caching for them marginally), it's hard to tell if any of these impact other tools
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you want to do that, I recommend reading the section go tool
of the golangci-lint doc https://golangci-lint.run/welcome/install/#install-from-sources
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, currently we have this issue from the other tools:
When using the "tools pattern" or tool command/directives, the dependencies of a tool can modify the dependencies of another tool or your project. The resulting binary was not tested and is not guaranteed to work.
Tracking it in a shared tools module has risks, I think we should split it out.
Then the only question is if we use a specific module or avoid a module entirely.
Using a module means we get GOSHASUM and other visibility, at the risk of breaking replace statements.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We prefer not to take opaque binary dependencies generally, and it's also more complex to do portably across OS-es. It is somewhat less opaque to track this way, and I see shasums breaking as a feature that indicates some unknown change was made that hasn't been looked at. The GOSHASUMS enable TOFU in a way that is much simpler and re-usable than binaries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh! it wasn't obvious that this expanded, and the lines above at the linked heading talk about go tool
Might be worth tweaking the styling / layout.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is intentionally not a heading because we strongly don't recommend that.
But I prefer to provide the right way to do it instead of letting users in the dark.
So this is a compromise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Installing golangci-lint through a separate module seems worthwhile. I've added one more commit doing that:
golangci-lint: move into hack/tools/golangci-lint
The advantage is that it separates the dependencies of the different tools
better. golangci-lint in particular has many dependencies and is sometimes
sensitive to the exact version being used. This way, "go get" bumps up
dependencies exactly as defined by the upstream golangci-lint module.
It's not quite self-contained because logcheck as a Go plugin for golangci-lint
must be built from the same dependencies. But it only adds one and does not
change any of the others.
While at it, the Go 1.24 "tools" directive gets used instead of the traditional
tools.go approach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/approve
for hack/
Need more eyes on the other changes to confirm.
@@ -644,7 +646,7 @@ func (dc *DisruptionController) processNextWorkItem(ctx context.Context) bool { | |||
return true | |||
} | |||
|
|||
utilruntime.HandleError(fmt.Errorf("Error syncing PodDisruptionBudget %v, requeuing: %w", dKey, err)) //nolint:stylecheck | |||
utilruntime.HandleErrorWithContext(ctx, err, "Error syncing PodDisruptionBudget", "key", dKey) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a curious change to pair with the lint v2 bump ... was the existing //nolint:stylecheck
comment suppressing an "errors start with lowercase letter" check? If so, this changed to context logging (which is a functional change that looks unrelated to the linting), but is still passing the initial uppercase message the stylecheck complained about?
At the very least, we should avoid dropping the "requeuing" bit from the message, so "Error syncing PodDisruptionBudget, requeuing"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
was the existing //nolint:stylecheck comment suppressing an "errors start with lowercase letter" check?
That check is not enforced. Perhaps //nolint
was added in https://github.com/kubernetes/kubernetes/blame/03a3c0c89161935bc2338f5754ebb1104f779af1/pkg/controller/disruption/disruption.go#L647 to silence the hint. That was unnecessary and in this case, I would have preferred fixing the code.
We should have a linter which complains about //nolint:something
without an additional comment after it (//nolint: // " Not relevant because ...
)...
If so, this changed to context logging (which is a functional change that looks unrelated to the linting),
We can:
- Leave this line as it is (including the
//nolint:stylecheck
, which is useless now because the linter is no longer active). - Remove just the
//nolint:stylecheck
. - Update the line to use current best practices (= use
HandleErrorWithContext
).
I prefer the last option.
but is still passing the initial uppercase message the stylecheck complained about?
HandleError
was a logging function in disguise with additional tooling that normal error logging doesn't have. Using fmt.Errorf
was (mis)used to produce a log message.
HandleErrorWithContext
explicitly accepts a log message and additional key/value pairs, in addition to the error (if there is one - it's not required, i.e. no need to fabricate a new one if there isn't one already). For log messages, the recommendation is to start with a capital letter. I'm not exactly sure why, that recommendation pre-dates my involvement.
TLDR: `Error syncing" is fine here.
At the very least, we should avoid dropping the "requeuing" bit from the message, so "Error syncing PodDisruptionBudget, requeuing"
Ack, changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should have a linter which complains about //nolint:something without an additional comment after it (//nolint: // " Not relevant because ...)...
You might want to take a look at whyNoLint rule from go-critic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or just nolintlint
https://golangci-lint.run/usage/linters/#nolintlint
nolintlint
is the official linter to handle nolint
directives.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggested whyNoLint because go-critic is already enabled in this project and also nolintlint has been deactivated on some projects for generating conflicts with other linters see this open issue golangci/golangci-lint#3228
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This problem is not a specific issue related to nolintlint and not related to comments, this is explained inside the issue.
@@ -65,7 +65,7 @@ func Convert_v1_JSON_To_apiextensions_JSON(in *JSON, out *apiextensions.JSON, s | |||
} | |||
*out = i | |||
} else { | |||
out = nil | |||
*out = nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
This change is correct, the linter was correct to flag the old code.
-
This change is also safe.
out
must be a non-nil pointer for conversion to work, and in all call sites, a non-nilout
pointer is passed. -
This change is also ultimately a no-op for existing callers because in all call sites, a nil
in
parameter is never passed.- This is either because the source is not a pointer, so is always non-nil:
Line 766 in c064ed8
if err := Convert_v1_JSON_To_apiextensions_JSON(&(*in)[i], &(*out)[i], s); err != nil { - Or the source is a pointer but the nil case is handled by directly assigning nil to the destination rather than calling
Convert_v1_JSON_To_apiextensions_JSON
:Lines 742 to 750 in c064ed8
if in.Default != nil { in, out := &in.Default, &out.Default *out = new(apiextensions.JSON) if err := Convert_v1_JSON_To_apiextensions_JSON(*in, *out, s); err != nil { return err } } else { out.Default = nil } Lines 898 to 906 in c064ed8
if in.Example != nil { in, out := &in.Example, &out.Example *out = new(apiextensions.JSON) if err := Convert_v1_JSON_To_apiextensions_JSON(*in, *out, s); err != nil { return err } } else { out.Example = nil }
- This is either because the source is not a pointer, so is always non-nil:
staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/conversion.go
Show resolved
Hide resolved
hack/verify-golangci-lint.sh
Outdated
@@ -153,9 +155,8 @@ if [ "${golangci_config}" ]; then | |||
# don't to do it when not required. | |||
if grep -q 'path: ../_output/local/bin/' "${golangci_config}" && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should the ..
be dropped from the grep if we're dropping it from the sed here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, thanks for catching this.
hack/verify-golangci-lint.sh
Outdated
echo "installing golangci-lint and logcheck plugin from hack/tools into ${GOBIN}" | ||
GOTOOLCHAIN="$(kube::golang::hack_tools_gotoolchain)" go -C "${KUBE_ROOT}/hack/tools" install github.com/golangci/golangci-lint/v2/cmd/golangci-lint | ||
GOWORK=off GOTOOLCHAIN="$(kube::golang::hack_tools_gotoolchain)" go -C "${KUBE_ROOT}/hack/tools/golangci-lint" install github.com/golangci/golangci-lint/v2/cmd/golangci-lint |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we already have a dummy go.work checked in for hack/tools/go.work that meant we didn't need to do GOWORK=off before ... I'm not 100% sure why we needed to do that ... is there any other reason to add a peer hack/tools/golangci-lint/go.work
? I think it would let us drop this disable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That also works. Changed.
checks: | ||
- "all" | ||
{{- if .Base }} | ||
- "-QF1001" # Apply De Morgan’s law |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are all these exclusions for checks that are new in v2, or did we start running entire linters we weren't running before? I'm surprised we have to exclude so many individual new checks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To my understanding gosimple and stylecheck have been merged into staticcheck and staticcheck is the only one left available in golangci-lint.
hack/golangci.yaml.in
Outdated
# The default is relative to the configuration, which is confusing because | ||
# then all paths start with ../ to move out of the "hack" directory. | ||
# `gomod` mirrors the current behavior of `golangci-lint.sh` changing into | ||
# the root. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... changing into the root
the root of k8s.io/kubernetes
or of the module being evaluated (when we evaluate stuff under staging/src/k8s.io/*
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed:
# `gomod` mirrors the current behavior of `golangci-lint.sh` changing into
# the root of the repository. Because we are operating in a workspace,
# the module picked by `gomod` is the main one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's tricky to understand how stuff in the old config translated to the new one. Was the v2 config auto-generated with https://golangci-lint.run/product/migration-guide/ or done by hand?
Is there a way to see which changes were mechanical v1 → v2 translations and which were intentional changes from how we configured v1 to behave?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think @mmorel-35 started by converting automatically because the initial commit in #131113 also included some re-ordering.
But some things are necessarily manual. I think we tried to stick as closely as possible to the original configuration, except for a few points where some cleanup was possible because something was obsolete (for example, a suppression because of a bug in the Ginkgo linter which had been fixed already long ago).
The important part is that the current code passes the base configuration. Not much had to be changed in the code to achieve that. If we find that the new configuration is too strong (whether its the base configuration or for hints), then we can always refine it in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The re-ordering is not related to automatic conversion, because the order is not the order produced by the automatic conversion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not anymore, because at some point I asked @mmorel-35 to restore the original order.
@mmorel-35: did you initially convert automatically?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I started with golangci-lint migrate and then align with existing config to ease review (restore comments, quoting, spacing...)
/cc |
- float-compare | ||
- formatter | ||
- len | ||
- useless-assert |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those rules are new or updated to discover more cases in testifylint and needs to be disabled so the base is still passing
Signed-off-by: Matthieu MOREL <[email protected]>
Passing a constant value to gomega.Consistently means that it will not re-check while running. Found by linter after removing the suppression rule for the check. It was disabled earlier because of a bug in the linter.
/test pull-kubernetes-integration TestVolumeBindingRescheduling timeout |
This finishes the work started in kubernetes#131113. Changes: - Remove TODOs for things that we don't have plans to fix. - Add issue for older TODO. - Reorganize and remove suppression rules so that the base check has no unused rules. - Document warn-unused, but don't enable it. - Remove disabling of statistics (they are useful) and ensure that they don't get the ERROR prefix. - Avoid ../ prefix in paths via `run.relative-path-mode: gomod`.
The advantage is that it separates the dependencies of the different tools better. golangci-lint in particular has many dependencies and is sometimes sensitive to the exact version being used. This way, "go get" bumps up dependencies exactly as defined by the upstream golangci-lint module. It's not quite self-contained because logcheck as a Go plugin for golangci-lint must be built from the same dependencies. But it only adds one and does not change any of the others. While at it, the Go 1.24 "tools" directive gets used instead of the traditional tools.go approach.
cc @kubernetes/sig-api-machinery-bugs
/retest |
LGTM label has been added. Git tree hash: 6c2f07f71e15663eb30eb985328b09a0756aec61
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: BenTheElder, liggitt, pohly The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
What type of PR is this?
/kind cleanup
What this PR does / why we need it:
This updates Kubernetes to use the new and revised golangci-lint v2. On this occasion, the check suppressions got revisited, revealing that in some cases existing code really is broken (fix included in this PR, see individual commits).
Special notes for your reviewer:
This is a continuation of #131113. See last commit for the differences.
Does this PR introduce a user-facing change?
/cc @mmorel-35 @ldez