Skip to content
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

verify-golangci-lint.sh: support stricter checking in new code #109728

Merged
merged 2 commits into from Mar 8, 2023

Conversation

pohly
Copy link
Contributor

@pohly pohly commented Apr 29, 2022

What type of PR is this?

/kind feature

What this PR does / why we need it:

It is useful to check new code with a stricter configuration because we want it
to be of higher quality. Code reviews also become easier when reviewers don't
need to point out inefficient code manually.

What exactly should be enabled is up for debate. The current config uses the
golangci-lint defaults plus everything that is enabled explicitly by the normal
.golangci.yaml, just to be on the safe side.

Special notes for your reviewer:

As a first step we could add a non-blocking pull job which runs with the stricter configuration for the new code, using -r PULL_BASE_REF.

kubernetes/test-infra#17056 would have been nice, but hasn't made much progress. Let's move forward by enabling strict linting in an optional job.

Does this PR introduce a user-facing change?

NONE

@k8s-ci-robot k8s-ci-robot added release-note-none Denotes a PR that doesn't merit a release note. kind/feature Categorizes issue or PR as related to a new feature. labels Apr 29, 2022
@k8s-ci-robot
Copy link
Contributor

Please note that we're already in Test Freeze for the release-1.24 branch. This means every merged PR has to be cherry-picked into the release branch to be part of the upcoming v1.24.0 release.

@k8s-ci-robot k8s-ci-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. do-not-merge/needs-sig Indicates an issue or PR lacks a `sig/foo` label and requires one. needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. needs-priority Indicates a PR lacks a `priority/foo` label and requires one. labels Apr 29, 2022
@pohly
Copy link
Contributor Author

pohly commented Apr 29, 2022

It is instructive to look at issues reported for recently added code, for example everything since v1.24.0-alpha.1. Code quality definitely could be better, and IMHO golangci-lint does a good job with pointing out relevant issues:

$ hack/verify-golangci-lint.sh -r v1.24.0-alpha.1 -s
installing golangci-lint and logcheck plugin from hack/tools into /nvme/gopath/src/k8s.io/kubernetes/_output/local/bin
running golangci-lint run --config=/nvme/gopath/src/k8s.io/kubernetes/.golangci-strict.yaml --new --new-from-rev=471b70c8b5a9f37f056a51d3656ceed7908c957c
pkg/credentialprovider/plugin/plugin.go:69:34: Error return value is not checked (errcheck)
	kubeletconfigv1beta1.AddToScheme(scheme)
	                                ^
cmd/yamlfmt/yamlfmt_test.go:51:30: S1030: should use output.String() instead of string(output.Bytes()) (gosimple)
	assert.Equal(t, outputYaml, string(output.Bytes()), "yaml was not formatted correctly")
	                            ^
test/e2e/windows/gmsa_full.go:505:51: Error return value of `(k8s.io/client-go/kubernetes/typed/rbac/v1.ClusterRoleBindingInterface).Create` is not checked (errcheck)
	f.ClientSet.RbacV1().ClusterRoleBindings().Create(context.TODO(), binding, metav1.CreateOptions{})
	                                                 ^
pkg/kubelet/nodeshutdown/nodeshutdown_manager_linux.go:323:31: Error return value of `m.dbusCon.ReleaseInhibitLock` is not checked (errcheck)
		m.dbusCon.ReleaseInhibitLock(m.inhibitLock)
		                            ^
test/e2e/autoscaling/horizontal_pod_autoscaling_behavior.go:80:18: S1012: should use `time.Since` instead of `time.Now().Sub` (gosimple)
			timeWaited := time.Now().Sub(waitStart)
			              ^
test/images/agnhost/grpc-health-checking/grpc-health-checking.go:104:10: Error return value of `w.Write` is not checked (errcheck)
		w.Write([]byte(data))
		       ^
test/images/agnhost/grpc-health-checking/grpc-health-checking.go:113:10: Error return value of `w.Write` is not checked (errcheck)
		w.Write([]byte(data))
		       ^
test/e2e/common/node/pod_admission.go:86:5: S1002: should omit comparison to bool constant, can be simplified to `!foundNode` (gosimple)
	if foundNode == false {
	   ^
test/e2e/scheduling/predicates.go:268:44: Error return value of `(k8s.io/client-go/kubernetes/typed/node/v1beta1.RuntimeClassInterface).Delete` is not checked (errcheck)
			cs.NodeV1beta1().RuntimeClasses().Delete(context.TODO(), e2enode.PreconfiguredRuntimeClassHandler, metav1.DeleteOptions{})
			                                        ^
test/integration/objectmeta/objectmeta_test.go:48:18: SA1019: nsNew.ZZZ_DeprecatedClusterName is deprecated: ClusterName is a legacy field that was always cleared by the system and never used; it will be removed completely in 1.25. (staticcheck)
	assert.Empty(t, nsNew.ZZZ_DeprecatedClusterName)
	                ^
test/integration/objectmeta/objectmeta_test.go:53:18: SA1019: nsNew.ZZZ_DeprecatedClusterName is deprecated: ClusterName is a legacy field that was always cleared by the system and never used; it will be removed completely in 1.25. (staticcheck)
	assert.Empty(t, nsNew.ZZZ_DeprecatedClusterName)
	                ^
test/integration/framework/controlplane_utils.go:172:8: Error return value of `v.Set` is not checked (errcheck)
		v.Set(strconv.Itoa(MinVerbosity))
		     ^
cmd/kubelet/app/options/options.go:326:19: Error return value of `fs.MarkDeprecated` is not checked (errcheck)
	fs.MarkDeprecated("experimental-mounter-path", "will be removed in 1.24 or later. in favor of using CSI.")
	                 ^
cmd/kubelet/app/options/options.go:328:19: Error return value of `fs.MarkDeprecated` is not checked (errcheck)
	fs.MarkDeprecated("cloud-provider", "will be removed in 1.24 or later, in favor of removing cloud provider code from Kubelet.")
	                 ^
cmd/kubelet/app/options/options.go:330:19: Error return value of `fs.MarkDeprecated` is not checked (errcheck)
	fs.MarkDeprecated("cloud-config", "will be removed in 1.24 or later, in favor of removing cloud provider code from Kubelet.")
	                 ^
cmd/kubelet/app/options/options.go:332:19: Error return value of `fs.MarkDeprecated` is not checked (errcheck)
	fs.MarkDeprecated("experimental-allocatable-ignore-eviction", "will be removed in 1.24 or later.")
	                 ^
pkg/registry/core/rest/storage_core.go:203:3: S1021: should merge variable declaration with assignment on next line (gosimple)
		var mem allocator.Snapshottable
		^
pkg/registry/core/rest/storage_core.go:223:4: S1021: should merge variable declaration with assignment on next line (gosimple)
			var mem allocator.Snapshottable
			^
test/e2e/storage/testsuites/snapshottable.go:185:30: Error return value of `e2epod.DeletePodWithWait` is not checked (errcheck)
					e2epod.DeletePodWithWait(cs, pod)
					                        ^
cmd/kube-apiserver/app/options/options.go:180:19: Error return value of `fs.MarkDeprecated` is not checked (errcheck)
	fs.MarkDeprecated("apiserver-count", "apiserver-count is deprecated and will be removed in a future version.")
	                 ^
pkg/controller/replicaset/replica_set.go:158:35: Error return value of `(k8s.io/client-go/tools/cache.SharedIndexInformer).AddIndexers` is not checked (errcheck)
	rsInformer.Informer().AddIndexers(cache.Indexers{
	                                 ^
pkg/volume/fc/fc_util.go:261:5: S1002: should omit comparison to bool constant, can be simplified to `!exists` (gosimple)
	if exists == false {
	   ^
test/integration/controlplane/transformation/transformation_testcase.go:106:43: Error return value of `(k8s.io/client-go/kubernetes/typed/core/v1.NamespaceInterface).Delete` is not checked (errcheck)
	e.restClient.CoreV1().Namespaces().Delete(context.TODO(), e.ns.Name, *metav1.NewDeleteOptions(0))
	                                         ^
pkg/apis/core/validation/validation_test.go:1363:5: SA1019: claim.ZZZ_DeprecatedClusterName is deprecated: ClusterName is a legacy field that was always cleared by the system and never used; it will be removed completely in 1.25. (staticcheck)
				claim.ZZZ_DeprecatedClusterName = "foo"
				^
pkg/kubelet/config/flags.go:55:19: Error return value of `fs.MarkDeprecated` is not checked (errcheck)
	fs.MarkDeprecated("container-runtime", "will be removed in 1.27 as the only valid value is 'remote'")
	                 ^
pkg/kubelet/config/flags.go:58:19: Error return value of `fs.MarkDeprecated` is not checked (errcheck)
	fs.MarkDeprecated("pod-infra-container-image", "will be removed in 1.27. Image garbage collector will get sandbox image information from CRI.")
	                 ^
pkg/kubelet/config/flags.go:57:83: S1039: unnecessary use of fmt.Sprintf (gosimple)
	fs.StringVar(&s.PodSandboxImage, "pod-infra-container-image", s.PodSandboxImage, fmt.Sprintf("Specified image will not be pruned by the image garbage collector. CRI implementations have their own configuration to set this image."))
	                                                                                 ^
test/integration/logs/benchmark/benchmark_test.go:276:30: SA1019: os.SEEK_SET has been deprecated since Go 1.7: Use io.SeekStart, io.SeekCurrent, and io.SeekEnd. (staticcheck)
			if _, err := file.Seek(0, os.SEEK_SET); err != nil {
			                          ^
pkg/printers/internalversion/printers.go:593:16: Error return value of `h.TableHandler` is not checked (errcheck)
	h.TableHandler(scaleColumnDefinitions, printScale)
	              ^
test/e2e/network/example_cluster_dns.go:107:44: Error return value of `e2eresource.WaitForControlledPodsRunning` is not checked (errcheck)
			e2eresource.WaitForControlledPodsRunning(c, ns.Name, backendName, api.Kind("ReplicationController"))
			                                        ^
test/e2e/network/example_cluster_dns.go:108:29: Error return value of `e2enetwork.WaitForService` is not checked (errcheck)
			e2enetwork.WaitForService(c, ns.Name, backendName, true, framework.Poll, framework.ServiceStartTimeout)
			                         ^
test/e2e/network/scale/ingress.go:319:15: Error return value of `os.WriteFile` is not checked (errcheck)
		os.WriteFile(f.OutputFile, []byte(formattedData), 0644)
		            ^
test/e2e/storage/drivers/in_tree.go:1503:32: Error return value of `node.VSphere.Client.Logout` is not checked (errcheck)
					node.VSphere.Client.Logout(context.TODO())
					                          ^
test/e2e/storage/csi_mock_volume.go:1403:76: Error return value of `(k8s.io/client-go/kubernetes/typed/storage/v1.CSIStorageCapacityInterface).Delete` is not checked (errcheck)
						f.ClientSet.StorageV1().CSIStorageCapacities(f.Namespace.Name).Delete(context.Background(), createdCapacity.Name, metav1.DeleteOptions{})
						                                                                     ^
pkg/proxy/ipvs/proxier.go:1407:35: Error return value of `conntrack.ClearEntriesForPort` is not checked (errcheck)
					conntrack.ClearEntriesForPort(proxier.exec, lp.Port, isIPv6, v1.ProtocolUDP)
					                             ^
pkg/proxy/ipvs/proxier.go:1563:68: S1030: should use proxier.iptablesData.String() instead of string(proxier.iptablesData.Bytes()) (gosimple)
			klog.ErrorS(err, "Failed to execute iptables-restore", "rules", string(proxier.iptablesData.Bytes()))
			                                                                ^
test/e2e/node/pods.go:437:28: Error return value of `expfmt.MetricFamilyToText` is not checked (errcheck)
		expfmt.MetricFamilyToText(&buf, m)
		                         ^
test/e2e/node/pods.go:613:32: S1002: should omit comparison to bool constant, can be simplified to `*status.Started` (gosimple)
		if (status.Started != nil && *status.Started == true) || status.LastTerminationState.Terminated != nil || status.State.Waiting == nil {
		                             ^
test/e2e/node/pods.go:465:2: S1008: should use 'return event.Type == watch.Deleted' instead of 'if event.Type == watch.Deleted { return true }; return false' (gosimple)
	if event.Type == watch.Deleted {
	^
pkg/volume/csi/csi_attacher.go:669:33: S1025: the argument is already a string, there's no need to use fmt.Sprintf (gosimple)
	result := sha256.Sum256([]byte(fmt.Sprintf("%s", csiSource.VolumeHandle)))
	                               ^
pkg/volume/csi/csi_attacher_test.go:1804:33: S1025: the argument is already a string, there's no need to use fmt.Sprintf (gosimple)
	result := sha256.Sum256([]byte(fmt.Sprintf("%s", handle)))
	                               ^
pkg/kubelet/stats/pidlimit/pidlimit_linux.go:62:18: Error return value of `syscall.Sysinfo` is not checked (errcheck)
		syscall.Sysinfo(&info)
		               ^
pkg/volume/testing/volume_host.go:67:2: `node` is unused (structcheck)
	node                   *v1.Node
	^
cmd/prune-junit-xml/prunexml_test.go:65:29: S1030: should use output.String() instead of string(output.Bytes()) (gosimple)
	assert.Equal(t, outputXML, string(output.Bytes()), "xml was not pruned correctly")
	                           ^
pkg/scheduler/framework/plugins/defaultpreemption/default_preemption.go:178:14: S1039: unnecessary use of fmt.Sprintf (gosimple)
		message := fmt.Sprintf("No preemption victims found for incoming pod")
		           ^
pkg/scheduler/framework/plugins/defaultpreemption/default_preemption.go:240:17: S1039: unnecessary use of fmt.Sprint (gosimple)
		return false, fmt.Sprint("not eligible due to preemptionPolicy=Never.")
		              ^
pkg/scheduler/framework/plugins/defaultpreemption/default_preemption.go:256:20: S1039: unnecessary use of fmt.Sprint (gosimple)
					return false, fmt.Sprint("not eligible due to a terminating pod on the nominated node.")
					              ^
pkg/registry/flowcontrol/ensurer/strategy.go:179:2: S1005: unnecessary assignment to the blank identifier (gosimple)
	value, _ := accessor.GetAnnotations()[flowcontrolv1beta2.AutoUpdateAnnotationKey]
	^
pkg/registry/rbac/helpers_test.go:193:3: SA1019: objMeta.ZZZ_DeprecatedClusterName is deprecated: ClusterName is a legacy field that was always cleared by the system and never used; it will be removed completely in 1.25. (staticcheck)
		objMeta.ZZZ_DeprecatedClusterName = ""
		^
test/e2e/framework/autoscaling/autoscaling_utils.go:709:73: Error return value of `(k8s.io/client-go/kubernetes/typed/autoscaling/v2.HorizontalPodAutoscalerInterface).Delete` is not checked (errcheck)
	rc.clientSet.AutoscalingV2().HorizontalPodAutoscalers(rc.nsName).Delete(context.TODO(), autoscalerName, metav1.DeleteOptions{})
	                                                                       ^
pkg/api/testing/applyconfiguration_test.go:182:5: SA1019: s.SelfLink is deprecated: selfLink is a legacy read-only field that is no longer populated by the system. +optional (staticcheck)
				s.SelfLink = ""
				^
pkg/api/testing/applyconfiguration_test.go:183:5: SA1019: s.ZZZ_DeprecatedClusterName is deprecated: ClusterName is a legacy field that was always cleared by the system and never used; it will be removed completely in 1.25. (staticcheck)
				s.ZZZ_DeprecatedClusterName = ""
				^
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/api
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver
staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/validation.go:156:56: S1039: unnecessary use of fmt.Sprintf (gosimple)
		errs = append(errs, field.Invalid(fldPath, sts.Type, fmt.Sprintf("validation failed due to running out of cost budget, no further validation rules will be run")))
		                                                     ^
staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/validation.go:188:59: S1039: unnecessary use of fmt.Sprintf (gosimple)
					errs = append(errs, field.Invalid(fldPath, sts.Type, fmt.Sprintf("validation failed due to running out of cost budget, no further validation rules will be run")))
					                                                     ^
staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler_test.go:825:8: S1004: should use !bytes.Equal(objBytes, expectedBytes) instead (gosimple)
				if bytes.Compare(objBytes, expectedBytes) != 0 {
				   ^
staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler_test.go:795:119: composites: `k8s.io/apimachinery/pkg/runtime/serializer/json.SerializerOptions` composite literal uses unkeyed fields (govet)
			delegate := serializerjson.NewSerializerWithOptions(serializerjson.DefaultMetaFactory, unstructuredCreator{}, nil, serializerjson.SerializerOptions{tc.yaml, false, tc.strictDecoding})
			                                                                                                                   ^
staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation.go:732:22: S1039: unnecessary use of fmt.Sprintf (gosimple)
					costErrorMsg := fmt.Sprintf("contributed to estimated rule cost total exceeding cost limit for entire OpenAPIv3 schema")
					                ^
staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation.go:1163:12: S1039: unnecessary use of fmt.Sprintf (gosimple)
		factor = fmt.Sprintf("more than 100x")
		         ^
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/apimachinery
staging/src/k8s.io/apimachinery/pkg/runtime/allocator.go:61:23: S1019: should use make([]byte, size) instead (gosimple)
	a.buf = make([]byte, size, size)
	                     ^
staging/src/k8s.io/apimachinery/pkg/runtime/allocator.go:73:22: S1019: should use make([]byte, n) instead (gosimple)
	return make([]byte, n, n)
	                    ^
staging/src/k8s.io/apimachinery/pkg/runtime/serializer/protobuf/protobuf_test.go:177:24: S1019: should use make([]byte, n) instead (gosimple)
	ta.buf = make([]byte, n, n)
	                      ^
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/apiserver
staging/src/k8s.io/apiserver/pkg/storage/etcd3/watcher_test.go:308:12: lostcancel: the cancel function returned by context.WithTimeout should be called, not discarded, to avoid a context leak (govet)
	watchCtx, _ := context.WithTimeout(ctx, wait.ForeverTestTimeout)
	          ^
staging/src/k8s.io/apiserver/pkg/storage/etcd3/store_test.go:779:7: SA1019: pod.SelfLink is deprecated: selfLink is a legacy read-only field that is no longer populated by the system. +optional (staticcheck)
						pod.SelfLink = "testlink"
						^
staging/src/k8s.io/apiserver/pkg/storage/etcd3/store_test.go:804:7: SA1019: out.SelfLink is deprecated: selfLink is a legacy read-only field that is no longer populated by the system. +optional (staticcheck)
			if out.SelfLink != "" {
			   ^
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/client-go
staging/src/k8s.io/client-go/util/testing/fake_openapi_handler.go:84:18: Error return value of `filepath.WalkDir` is not checked (errcheck)
	filepath.WalkDir(specsPath, func(path string, d fs.DirEntry, err error) error {
	                ^
staging/src/k8s.io/client-go/util/testing/fake_openapi_handler.go:104:45: Error return value of `openAPIVersionedService.UpdateGroupVersion` is not checked (errcheck)
		openAPIVersionedService.UpdateGroupVersion(gv, spec)
		                                          ^
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/cli-runtime
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/cloud-provider
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/cluster-bootstrap
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/code-generator
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/component-base
staging/src/k8s.io/component-base/logs/json/register/register_test.go:72:13: composites: `k8s.io/component-base/logs.Options` composite literal uses unkeyed fields (govet)
				return &logs.Options{*c}
				        ^
staging/src/k8s.io/component-base/logs/example/cmd/logger.go:67:22: Error return value of `logs.AddFeatureGates` is not checked (errcheck)
	logs.AddFeatureGates(featureGate)
	                    ^
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/component-helpers
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/controller-manager
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/cri-api
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/csi-translation-lib
staging/src/k8s.io/csi-translation-lib/plugins/vsphere_volume.go:239:18: Error return value is not checked (errcheck)
		replaceTopology(pv, zoneLabel, csiTopologyKeyZone)
		               ^
staging/src/k8s.io/csi-translation-lib/plugins/vsphere_volume.go:244:16: Error return value is not checked (errcheck)
				addTopology(pv, csiTopologyKeyZone, []string{label})
				           ^
staging/src/k8s.io/csi-translation-lib/plugins/vsphere_volume.go:252:18: Error return value is not checked (errcheck)
		replaceTopology(pv, regionLabel, csiTopologyKeyRegion)
		               ^
staging/src/k8s.io/csi-translation-lib/plugins/vsphere_volume.go:257:16: Error return value is not checked (errcheck)
				addTopology(pv, csiTopologyKeyRegion, []string{label})
				           ^
staging/src/k8s.io/csi-translation-lib/plugins/vsphere_volume_test.go:43:34: composites: `k8s.io/api/core/v1.TopologySelectorTerm` composite literal uses unkeyed fields (govet)
	expectedTopologySelectorTerm := v1.TopologySelectorTerm{[]v1.TopologySelectorLabelRequirement{
	                                ^
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/kube-aggregator
staging/src/k8s.io/kube-aggregator/pkg/controllers/openapiv3/aggregator/aggregator.go:102:63: Error return value of `s.openAPIV2ConverterHandler.RegisterOpenAPIV3VersionedService` is not checked (errcheck)
	s.openAPIV2ConverterHandler.RegisterOpenAPIV3VersionedService("/openapi/v3", openAPIV2ConverterMux)
	                                                             ^
staging/src/k8s.io/kube-aggregator/pkg/controllers/openapiv3/aggregator/aggregator.go:168:49: Error return value of `s.openAPIV2ConverterHandler.UpdateGroupVersion` is not checked (errcheck)
		s.openAPIV2ConverterHandler.UpdateGroupVersion(getGroupVersionStringFromAPIService(apiService.apiService), v3Spec)
		                                              ^
staging/src/k8s.io/kube-aggregator/pkg/controllers/openapiv3/aggregator/aggregator.go:169:31: Error return value of `s.updateAPIServiceSpecLocked` is not checked (errcheck)
		s.updateAPIServiceSpecLocked(openAPIV2Converter)
		                            ^
staging/src/k8s.io/kube-aggregator/pkg/controllers/openapiv3/aggregator/aggregator_test.go:117:5: S1004: should use !bytes.Equal(gotSpecJSON, expectedV3Bytes) instead (gosimple)
	if bytes.Compare(gotSpecJSON, expectedV3Bytes) != 0 {
	   ^
staging/src/k8s.io/kube-aggregator/pkg/controllers/openapiv3/aggregator/aggregator_test.go:156:5: S1004: should use !bytes.Equal(gotSpecJSON, specJSON) instead (gosimple)
	if bytes.Compare(gotSpecJSON, specJSON) != 0 {
	   ^
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/kube-controller-manager
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/kubectl
staging/src/k8s.io/kubectl/pkg/util/completion/completion.go:202:7: Error return value of `o.Run` is not checked (errcheck)
	o.Run(f, cmd, args)
	     ^
staging/src/k8s.io/kubectl/pkg/util/completion/completion.go:272:19: Error return value of `o.RunAPIResources` is not checked (errcheck)
	o.RunAPIResources(cmd, f)
	                 ^
staging/src/k8s.io/kubectl/pkg/cmd/version/version.go:89:28: Error return value of `(*github.com/spf13/pflag.FlagSet).MarkDeprecated` is not checked (errcheck)
	cmd.Flags().MarkDeprecated("short", "and will be removed in the future. The --short output will become the default.")
	                          ^
staging/src/k8s.io/kubectl/pkg/cmd/version/version.go:112:10: S1028: should use fmt.Errorf(...) instead of errors.New(fmt.Sprintf(...)) (gosimple)
		return errors.New(fmt.Sprintf("extra arguments: %v", args))
		       ^
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/kubelet
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/kube-proxy
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/kube-scheduler
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/legacy-cloud-providers
staging/src/k8s.io/legacy-cloud-providers/vsphere/vclib/utils.go:259:3: S1008: should use 'return v.Major <= o.Major' instead of 'if v.Major > o.Major { return false }; return true' (gosimple)
		if v.Major > o.Major {
		^
staging/src/k8s.io/legacy-cloud-providers/vsphere/vclib/utils.go:265:3: S1008: should use 'return v.Minor <= o.Minor' instead of 'if v.Minor > o.Minor { return false }; return true' (gosimple)
		if v.Minor > o.Minor {
		^
staging/src/k8s.io/legacy-cloud-providers/vsphere/vclib/utils.go:271:3: S1008: should use 'return v.Revision <= o.Revision' instead of 'if v.Revision > o.Revision { return false }; return true' (gosimple)
		if v.Revision > o.Revision {
		^
staging/src/k8s.io/legacy-cloud-providers/vsphere/vclib/utils.go:277:3: S1008: should use 'return v.Build <= o.Build' instead of 'if v.Build > o.Build { return false }; return true' (gosimple)
		if v.Build > o.Build {
		^
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/metrics
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/mount-utils
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/pod-security-admission
staging/src/k8s.io/pod-security-admission/policy/registry_test.go:152:35: composites: `k8s.io/pod-security-admission/api.LevelVersion` composite literal uses unkeyed fields (govet)
		results := registry.EvaluatePod(api.LevelVersion{tc.level, versionOrPanic(tc.version)}, nil, nil)
		                                ^
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/sample-apiserver
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/sample-cli-plugin
running golangci-lint for /nvme/gopath/src/k8s.io/kubernetes/staging/src/k8s.io/sample-controller

Please review the above warnings. You can test via "./hack/verify-golangci-lint.sh -r v1.24.0-alpha.1 -s"
If the above warnings do not make sense, you can exempt this warning with a comment
 (if your reviewer is okay with it).
The more strict .golangci-strict.yaml was used. If you feel that this warns about issues
that should be ignored by default, then please discuss with your reviewer and propose
a change for .golangci-strict.yaml as part of your PR.
In general please prefer to fix the error, we have already disabled specific lints
 that the project chooses to ignore.
See: https://golangci-lint.run/usage/false-positives/

if [ "$strict" ]; then
echo 'The more strict .golangci-strict.yaml was used. If you feel that this warns about issues'
echo 'that should be ignored by default, then please discuss with your reviewer and propose'
echo 'a change for .golangci-strict.yaml as part of your PR.'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is up for debate. I think it will be important to document the escalation path here, but it doesn't have to be this way.

The elephant in the room is: who has the authority to decide about the checks that new code has to pass?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hack/ OWNERS, who will also be approving the script itself and other similar lints?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That looks like a set of individuals, not any particular SIG. That's fine with me, I was really just wondering whether there is a SIG which is responsible for code quality questions.

Should .golangci-strict.yaml then be under hack, too? .golangci.yaml was placed in the root because that is where golangci-lint found it when walking up the stack, but the script doesn't rely on that anymore.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see! I think code organization is the closest thing at the moment as a specific subset of architecture, but typically tooling for code quality would be sig testing or more narrow like the logging linter.

I am a proponent of not dumping everything in the repo root both for ease of approvals and for making things less cluttered to discover ... The only counterpoint I can think of is if people try to run outside of our scripts, but that already doesn't make much sense for the non-default config. (It also probably doesn't work well anyhow for the other one)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fully agreed. It also doesn't need to be a dot file anymore... will change it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC we had to add it to the top because there was to be additional executions of the golangci-lint process so we can lint the modules too

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When using the --config parameter, the file can be anywhere.

So perhaps I should also move .golangci.yaml, unless someone can think of a reason why it needs to be in the root?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any problem if it works for the vendored modules, @thockin played with it a bit more

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file gets moved as part of #116166.

@aojea
Copy link
Member

aojea commented May 1, 2022

/sig testing
/sig architecture

I'm +1 on make more use of the linters

/assign @wojtek-t @thockin @dims @BenTheElder

@k8s-ci-robot k8s-ci-robot added the sig/testing Categorizes an issue or PR as relevant to SIG Testing. label May 1, 2022
@k8s-ci-robot k8s-ci-robot added sig/architecture Categorizes an issue or PR as relevant to SIG Architecture. and removed do-not-merge/needs-sig Indicates an issue or PR lacks a `sig/foo` label and requires one. labels May 1, 2022
@pohly
Copy link
Contributor Author

pohly commented May 2, 2022

Are there reasons for or against running this linting in a GitHub action?

A GitHub action might be simplest because it already has permission to publish comments. I don't know whether Prow jobs can do that.

But it would be different from the rest of the tests and we'd rely on compute resources provided by GitHub.

@pohly
Copy link
Contributor Author

pohly commented May 2, 2022

I have added a Kubernetes specific linter plugin for #109600. It's just a proot-of-concept (needs more tests and additional work) and should be merged separately, but I wanted to demonstrate that regardless of what we think about enabling the default golangci-lint checks, this approach would also be useful for other checks.

New ExpectNoError calls without explanation were added since v1.24.0-alpha.0 (just checking one package here):

$ _output/local/bin/golangci-lint cache clean && GOWORK=off hack/verify-golangci-lint.sh -r v1.24.0-alpha.0 -s ./test/e2e/storage/testsuites
installing golangci-lint and plugins from hack/tools into /nvme/gopath/src/k8s.io/kubernetes/_output/local/bin
running golangci-lint run --config=/nvme/gopath/src/k8s.io/kubernetes/.golangci-strict.yaml --new --new-from-rev=cad66fdfe5e1891bcadd4c8a7128f2fd0c24f037
test/e2e/storage/testsuites/provisioning.go:455:46: Error return value of `e2evolume.WaitForVolumeAttachmentTerminated` is not checked (errcheck)
		e2evolume.WaitForVolumeAttachmentTerminated(volumeAttachment, f.ClientSet, f.Timeouts.DataSourceProvision)
		                                           ^
test/e2e/storage/testsuites/provisioning.go:511:48: Error return value of `e2evolume.WaitForVolumeAttachmentTerminated` is not checked (errcheck)
				e2evolume.WaitForVolumeAttachmentTerminated(volumeAttachment, f.ClientSet, f.Timeouts.DataSourceProvision)
				                                           ^
test/e2e/storage/testsuites/snapshottable.go:185:30: Error return value of `e2epod.DeletePodWithWait` is not checked (errcheck)
					e2epod.DeletePodWithWait(cs, pod)
					                        ^
test/e2e/storage/testsuites/provisioning.go:262:3: function "ExpectNoError" should be called with a printf-style explanation (e2echeck)
		framework.ExpectNoError(err)
		^
test/e2e/storage/testsuites/provisioning.go:278:3: function "ExpectNoError" should be called with a printf-style explanation (e2echeck)
		framework.ExpectNoError(err)
		^
test/e2e/storage/testsuites/provisioning.go:286:3: function "ExpectNoError" should be called with a printf-style explanation (e2echeck)
		framework.ExpectNoError(err)
		^
test/e2e/storage/testsuites/provisioning.go:328:3: function "ExpectNoError" should be called with a printf-style explanation (e2echeck)
		framework.ExpectNoError(err)
		^
test/e2e/storage/testsuites/provisioning.go:351:3: function "ExpectNoError" should be called with a printf-style explanation (e2echeck)
		framework.ExpectNoError(err)
		^
test/e2e/storage/testsuites/provisioning.go:383:3: function "ExpectNoError" should be called with a printf-style explanation (e2echeck)
		framework.ExpectNoError(err)
		^
test/e2e/storage/testsuites/provisioning.go:1169:2: function "ExpectNoError" should be called with a printf-style explanation (e2echeck)
	framework.ExpectNoError(err)
	^
test/e2e/storage/testsuites/provisioning.go:1172:3: function "ExpectNoError" should be called with a printf-style explanation (e2echeck)
		framework.ExpectNoError(e2epod.DeletePodWithWait(client, pod1))
		^
test/e2e/storage/testsuites/provisioning.go:1178:2: function "ExpectNoError" should be called with a printf-style explanation (e2echeck)
	framework.ExpectNoError(err)
	^
test/e2e/storage/testsuites/provisioning.go:1205:2: function "ExpectNoError" should be called with a printf-style explanation (e2echeck)
	framework.ExpectNoError(err)
	^
test/e2e/storage/testsuites/provisioning.go:1209:2: function "ExpectNoError" should be called with a printf-style explanation (e2echeck)
	framework.ExpectNoError(e2epod.DeletePodWithWait(client, pod2))
	^
test/e2e/storage/testsuites/snapshottable.go:298:5: function "ExpectNoError" should be called with a printf-style explanation (e2echeck)
				framework.ExpectNoError(err)
				^
test/e2e/storage/testsuites/snapshottable.go:361:6: function "ExpectNoError" should be called with a printf-style explanation (e2echeck)
					framework.ExpectNoError(sr.CleanupResource(f.Timeouts))
					^
test/e2e/storage/testsuites/snapshottable.go:413:5: function "ExpectNoError" should be called with a printf-style explanation (e2echeck)
				framework.ExpectNoError(err)
				^
test/e2e/storage/testsuites/snapshottable.go:440:2: function "ExpectNoError" should be called with a printf-style explanation (e2echeck)
	framework.ExpectNoError(err)
	^
test/e2e/storage/testsuites/snapshottable.go:446:3: function "ExpectNoError" should be called with a printf-style explanation (e2echeck)
		framework.ExpectNoError(err)
		^
test/e2e/storage/testsuites/snapshottable.go:450:3: function "ExpectError" should be called with a printf-style explanation (e2echeck)
		framework.ExpectError(err)
		^
test/e2e/storage/testsuites/snapshottable.go:461:2: function "ExpectNoError" should be called with a printf-style explanation (e2echeck)
	framework.ExpectNoError(err)
	^
test/e2e/storage/testsuites/snapshottable.go:467:2: function "ExpectNoError" should be called with a printf-style explanation (e2echeck)
	framework.ExpectNoError(err)
	^

Please review the above warnings. You can test via "./hack/verify-golangci-lint.sh -r v1.24.0-alpha.0 -s ./test/e2e/storage/testsuites"
If the above warnings do not make sense, you can exempt this warning with a comment
 (if your reviewer is okay with it).
The more strict .golangci-strict.yaml was used. If you feel that this warns about issues
that should be ignored by default, then please discuss with your reviewer and propose
a change for .golangci-strict.yaml as part of your PR.
In general please prefer to fix the error, we have already disabled specific lints
 that the project chooses to ignore.
See: https://golangci-lint.run/usage/false-positives/

@k8s-ci-robot k8s-ci-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. area/dependency Issues or PRs related to dependency changes and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels May 2, 2022
@BenTheElder
Copy link
Member

Are there reasons for or against running this linting in a GitHub action?

GitHub actions don't work as well for blocking merge. In particular we cannot guarantee that we've tested the merged state prior to merge.

Having multiple CI in a repo may add additional confusion for other reasons. But we've done it elsewhere (e.g. in KIND).

A GitHub action might be simplest because it already has permission to publish comments. I don't know whether Prow jobs can do that.

We have some jobs with github tokens for commenting (think the triage robot), so it's very possible. In either case securing the token and limiting its usage is problematic.

@pohly
Copy link
Contributor Author

pohly commented May 2, 2022

Having multiple CI in a repo may add additional confusion for other reasons. But we've done it elsewhere (e.g. in KIND).

I've looked at how the golangci-lint GitHub action works and my conclusion is that we probably would have to fork it if we want it to work with current Kubernetes. It might work better once we use a workspace to build all of Kubernetes, but even then it would be different.

My preference is to enable annotations from a Prow job - see also my question on Slack: https://kubernetes.slack.com/archives/C01672LSZL0/p1651495487499899

@pohly pohly force-pushed the lint-pull-requests branch 2 times, most recently from 704ed2d to 4639f11 Compare May 3, 2022 14:13
@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Mar 7, 2023
It is useful to check new code with a stricter configuration because we want it
to be of higher quality. Code reviews also become easier when reviewers don't
need to point out inefficient code manually.

What exactly should be enabled is up for debate. The current config uses the
golangci-lint defaults plus everything that is enabled explicitly by the normal
golangci.yaml, just to be on the safe side.
The long-term goal is that when "make verify" is invoked in pull job, it will
also run golangci-lint with the strict configuration and write an
$ARTIFACTS/golangci-lint-githubactions.log file with GitHub actions
annotations. How to get those published for the GitHub PR is open.

When "make verify" is invoked manually or in any other job, the stricter check
will be skipped. That works because "PR_NUMBER" is only set for pre-merge
jobs (https://github.com/kubernetes/test-infra/blob/master/prow/jobs.md#job-environment-variables).

Because strict linting is still new and might not be useful without a better
UI (= GitHub annotations), this PR does not fully enable the integration into
"make verify". Instead, the new verify-golangci-lint-pr.sh is excluded from it
and needs to be run in a separate job.
@k8s-ci-robot k8s-ci-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Mar 7, 2023
@pohly
Copy link
Contributor Author

pohly commented Mar 7, 2023

Let me also call out that the acfa78b commit which failed pull-kubernetes-verify-strict-lint passed pull-kubernetes-verify, as intended: https://prow.k8s.io/pr-history/?org=kubernetes&repo=kubernetes&pr=109728

@pohly
Copy link
Contributor Author

pohly commented Mar 7, 2023

Next steps once this is merged (roughly in this order):

  • reply to https://groups.google.com/a/kubernetes.io/g/dev/c/myGiml72IbM/m/jzaFiYxJAgAJ and ask reviewers to use /test pull-kubernetes-verify-strict-lint and developers to use hack/verify-golangci-lint.sh -s -a (= "check my new code in a branch using the strict config").
  • optional: run the new job for all PRs while still not blocking
  • enable the strict checking for new code in pull-kubernetes-verify (blocking!)
  • ask contributors to fix issues in existing code (hack/verify-golangci-lint.sh -s)
  • enable linters that don't find issues also for existing code (for consistency and "just in case" - it shouldn't be possible to regress because new code needs to pass)

Copy link
Member

@BenTheElder BenTheElder left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

patrick brought this to the sig testing meeting again today and I think we have a good path forward here:

  • test a bit in non-blocking job
  • move this into pull-kubernetes-verify so we can reuse the golangci-lint cache and keep costs down, while only failing additional linters on net-new code
  • if we manage to cleanup all old code, we can move linters between the two config files. we don't have a mechanism to enforce that, but since new diffs will have the linter enforced, we can just perform this by first adding the now-always-passing linter to the "non strict" lint and then rotate it out of the stricter lint, when we manually identify that we've reached this point. We can consider filing tracking issues to ask people to work on this.

/lgtm
/approve

Thank you for persevering here.


usage () {
cat <<EOF >&2
Usage: $0 [-- <golangci-lint run flags>] [packages]"
Usage: $0 [-r <revision>|-a] [-s] [-c none|<config>] [-- <golangci-lint run flags>] [packages]"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this gets much more complex I'm going to suggest a go binary but this repo is already full of complicated bash :-)

- ineffassign

linters:
enable: # please keep this alphabetized
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add a comment about how this should only contain linters not already in the standard yaml?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(this should not block merging, but I think it might be helpful for future review context)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it absolutely should contain those 😅

That way, developers can be sure that verify-golangci-lint.sh -a -s catches all linter issues in their code and won't be surprised later when the "normal" config gets applied to it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And when the time comes to integrate it into pull-kubernetes-verify, it'll be enough to run verify-golangci-lint.sh only once, with the strict config.

I had a comment about that in the file at some point, but must have lost it when syncing anew with a modified golangci.yaml - I'll bring that comment back.

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Mar 7, 2023
@k8s-ci-robot
Copy link
Contributor

LGTM label has been added.

Git tree hash: dca7a342299803ac455668cf9268d9f79f3588e3

@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: BenTheElder, 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 /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Mar 7, 2023
@k8s-triage-robot
Copy link

The Kubernetes project has merge-blocking tests that are currently too flaky to consistently pass.

This bot retests PRs for certain kubernetes repos according to the following rules:

  • The PR does have any do-not-merge/* labels
  • The PR does not have the needs-ok-to-test label
  • The PR is mergeable (does not have a needs-rebase label)
  • The PR is approved (has cncf-cla: yes, lgtm, approved labels)
  • The PR is failing tests required for merge

You can:

/retest

@k8s-ci-robot k8s-ci-robot merged commit c24dc77 into kubernetes:master Mar 8, 2023
SIG Node PR Triage automation moved this from Needs Reviewer to Done Mar 8, 2023
@k8s-ci-robot k8s-ci-robot added this to the v1.27 milestone Mar 8, 2023
pohly added a commit to pohly/kubernetes that referenced this pull request Mar 8, 2023
kubernetes#109728 added a
golangci-strict.yaml where gingkolinter and stylecheck (some recent additions
to golangci.yaml) were missing.

To prevent such mistakes in the future, lines that are intentionally different
get annotated with a comment about golangci-strict.yaml or golangci.yaml.
Then a suitable diff command in the new verify-golangci-lint-config.sh checks
that only such lines, comments and blank lines are different.
pohly added a commit to pohly/kubernetes that referenced this pull request Mar 8, 2023
kubernetes#109728 added a
golangci-strict.yaml where gingkolinter and stylecheck (some recent additions
to golangci.yaml) were missing.

To prevent such mistakes in the future, lines that are intentionally different
get annotated with a comment about golangci-strict.yaml or golangci.yaml.
Then a suitable diff command in the new verify-golangci-lint-config.sh checks
that only such lines, comments and blank lines are different.
rayowang pushed a commit to rayowang/kubernetes that referenced this pull request Feb 9, 2024
All wrappers except for ExpectNoError are identical to their gomega
counterparts. The only advantage that they have is that their invocations are
shorter.

That advantage does not outweigh their disadvantages:
- cannot be used in combination with gomega.Eventually/Consistently
- not a full replacement for gomega, so we just end up using both
- don't support passing a stack offset and thus cannot be used in helper
  functions
- ginkgolinter does not work for them, so sub-optimal calls like this one
  are not reported:

     framework.ExpectEqual(len(items), 0)
     ->
     gomega.Expect(items).To(gomega.BeEmpty())
- developers try to make do with what's available in the framework, leading
  to sub-optimal checks like this:

    framework.ExpectEqual(true, strings.Contains(event.Message, expectedEventError), "Event error should indicate non-root policy caused container to not start")
    ->
    gomega.Expect(event.Message).To(gomega.ContainSubstring(expectedEventError), "Event error should indicate non-root policy caused container to not start")

So let's remove these wrappers. As a first step they get marked as deprecated.
This enables stricter
linting (kubernetes#109728), once enabled,
to report new code which uses them.
rayowang pushed a commit to rayowang/kubernetes that referenced this pull request Feb 9, 2024
kubernetes#109728 added a
golangci-strict.yaml where gingkolinter and stylecheck (some recent additions
to golangci.yaml) were missing.

To prevent such mistakes in the future, lines that are intentionally different
get annotated with a comment about golangci-strict.yaml or golangci.yaml.
Then a suitable diff command in the new verify-golangci-lint-config.sh checks
that only such lines, comments and blank lines are different.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. area/apiserver area/cloudprovider area/kubectl area/kubelet area/test cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/feature Categorizes issue or PR as related to a new feature. lgtm "Looks good to me", indicates that a PR is ready to be merged. priority/important-longterm Important over the long term, but may not be staffed and/or may need multiple releases to complete. release-note-none Denotes a PR that doesn't merit a release note. sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery. sig/apps Categorizes an issue or PR as relevant to SIG Apps. sig/architecture Categorizes an issue or PR as relevant to SIG Architecture. sig/auth Categorizes an issue or PR as relevant to SIG Auth. sig/cli Categorizes an issue or PR as relevant to SIG CLI. sig/cloud-provider Categorizes an issue or PR as relevant to SIG Cloud Provider. sig/instrumentation Categorizes an issue or PR as relevant to SIG Instrumentation. sig/network Categorizes an issue or PR as relevant to SIG Network. sig/node Categorizes an issue or PR as relevant to SIG Node. sig/storage Categorizes an issue or PR as relevant to SIG Storage. sig/testing Categorizes an issue or PR as relevant to SIG Testing. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. triage/accepted Indicates an issue or PR is ready to be actively worked on. wg/structured-logging Categorizes an issue or PR as relevant to WG Structured Logging.
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

None yet