Repository: helm/helm
Pull request #10575 (2022-01-18 16:19:59)

chore (lint): Replace golint with revive
`golint` which is used as one of the sub-linters in [golangci-lint](https://github.com/golangci/golangci-lint) is deprecated.
It is replaced with `revive` which is a drop-in replacement.

Signed-off-by: Martin Hickey <martin.hickey@ie.ibm.com>

Co-authored-by: Martin Mulholland <mmulholl@redhat.com>

**What this PR does / why we need it**:
[golangci-lint](https://github.com/golangci/golangci-lint) [deprecated the `golint` sublinter](https://github.com/golangci/golangci-lint/issues/1892). It needs to be replaced with `revive`.

This PR supersedes #10206 

**Special notes for your reviewer**:
How to handle the deprecation notices in the future is discussed here: golangci/golangci-lint#1987

Lint errors when `revive` aded as a sub-linter:

```console
$ make test-style

GO111MODULE=on golangci-lint run
pkg/registry/client.go:299:15: errorf: should replace errors.New(fmt.Sprintf(...)) with fmt.Errorf(...) (revive)
		return nil, errors.New(
			fmt.Sprintf("manifest does not contain minimum number of descriptors (%d), descriptors found: %d",
				minNumDescriptors, numDescriptors))
pkg/registry/client.go:321:15: errorf: should replace errors.New(fmt.Sprintf(...)) with fmt.Errorf(...) (revive)
		return nil, errors.New(
			fmt.Sprintf("could not load config with mediatype %s", ConfigMediaType))
pkg/registry/client.go:325:15: errorf: should replace errors.New(fmt.Sprintf(...)) with fmt.Errorf(...) (revive)
		return nil, errors.New(
			fmt.Sprintf("manifest does not contain a layer with mediatype %s",
				ChartLayerMediaType))
pkg/cli/environment_test.go:54:3: var-naming: don't use leading k in Go names; struct field kAsUser should be asUser (revive)
		kAsUser      string
		^
pkg/cli/environment_test.go:55:3: var-naming: don't use leading k in Go names; struct field kAsGroups should be asGroups (revive)
		kAsGroups    []string
		^
pkg/cli/environment_test.go:56:3: var-naming: don't use leading k in Go names; struct field kCaFile should be caFile (revive)
		kCaFile      string
		^
cmd/helm/completion_test.go:50:4: errorf: should replace t.Error(fmt.Sprintf(...)) with t.Errorf(...) (revive)
			t.Error(fmt.Sprintf("Unexpected directive ShellCompDirectiveNoFileComp when completing '%s'", cmdName))
			^
cmd/helm/completion_test.go:53:4: errorf: should replace t.Error(fmt.Sprintf(...)) with t.Errorf(...) (revive)
			t.Error(fmt.Sprintf("Did not receive directive ShellCompDirectiveNoFileComp when completing '%s'", cmdName))
			^
make: *** [test-style] Error 1

$ make test-style 

GO111MODULE=on golangci-lint run
pkg/chartutil/validate_name.go:43:19: errorf: should replace errors.New(fmt.Sprintf(...)) with fmt.Errorf(...) (revive)
	errInvalidName = errors.New(fmt.Sprintf(
		"invalid release name, must match regex %s and the length must not be longer than 53",
		validName.String()))
pkg/chartutil/validate_name.go:49:29: errorf: should replace errors.New(fmt.Sprintf(...)) with fmt.Errorf(...) (revive)
	errInvalidKubernetesName = errors.New(fmt.Sprintf(
		"invalid metadata name, must match regex %s and the length must not be longer than 253",
		validName.String()))
pkg/cli/environment_test.go:69:4: unknown field `kAsUser` in struct literal (typecheck)
			kAsUser:    "poro",
			^
pkg/cli/environment_test.go:70:4: unknown field `kAsGroups` in struct literal (typecheck)
			kAsGroups:  []string{"admins", "teatime", "snackeaters"},
			^
pkg/cli/environment_test.go:71:4: unknown field `kCaFile` in struct literal (typecheck)
			kCaFile:    "/tmp/ca.crt",
			^
pkg/cli/environment_test.go:79:4: unknown field `kAsUser` in struct literal (typecheck)
			kAsUser:    "pikachu",
			^
pkg/cli/environment_test.go:80:4: unknown field `kAsGroups` in struct literal (typecheck)
			kAsGroups:  []string{"operators", "snackeaters", "partyanimals"},
			^
pkg/cli/environment_test.go:81:4: unknown field `kCaFile` in struct literal (typecheck)
			kCaFile:    "/tmp/ca.crt",
			^
pkg/cli/environment_test.go:90:4: unknown field `kAsUser` in struct literal (typecheck)
			kAsUser:    "poro",
			^
pkg/cli/environment_test.go:91:4: unknown field `kAsGroups` in struct literal (typecheck)
			kAsGroups:  []string{"admins", "teatime", "snackeaters"},
			^
pkg/cli/environment_test.go:92:4: unknown field `kCaFile` in struct literal (typecheck)
			kCaFile:    "/my/ca.crt",
			^
pkg/cli/environment_test.go:122:10: tt.kAsUser undefined (type struct{name string; args string; envvars map[string]string; ns string; kcontext string; debug bool; maxhistory int; asUser string; asGroups []string; caFile string} has no field or method kAsUser) (typecheck)
			if tt.kAsUser != settings.KubeAsUser {
			      ^
pkg/cli/environment_test.go:123:48: tt.kAsUser undefined (type struct{name string; args string; envvars map[string]string; ns string; kcontext string; debug bool; maxhistory int; asUser string; asGroups []string; caFile string} has no field or method kAsUser) (typecheck)
				t.Errorf("expected kAsUser %q, got %q", tt.kAsUser, settings.KubeAsUser)
				                                           ^
pkg/cli/environment_test.go:125:29: tt.kAsGroups undefined (type struct{name string; args string; envvars map[string]string; ns string; kcontext string; debug bool; maxhistory int; asUser string; asGroups []string; caFile string} has no field or method kAsGroups) (typecheck)
			if !reflect.DeepEqual(tt.kAsGroups, settings.KubeAsGroups) {
			                         ^
pkg/cli/environment_test.go:126:56: tt.kAsGroups undefined (type struct{name string; args string; envvars map[string]string; ns string; kcontext string; debug bool; maxhistory int; asUser string; asGroups []string; caFile string} has no field or method kAsGroups) (typecheck)
				t.Errorf("expected kAsGroups %+v, got %+v", len(tt.kAsGroups), len(settings.KubeAsGroups))
				                                                   ^
pkg/cli/environment_test.go:128:10: tt.kCaFile undefined (type struct{name string; args string; envvars map[string]string; ns string; kcontext string; debug bool; maxhistory int; asUser string; asGroups []string; caFile string} has no field or method kCaFile) (typecheck)
			if tt.kCaFile != settings.KubeCaFile {
			      ^
pkg/cli/environment_test.go:129:48: tt.kCaFile undefined (type struct{name string; args string; envvars map[string]string; ns string; kcontext string; debug bool; maxhistory int; asUser string; asGroups []string; caFile string} has no field or method kCaFile) (typecheck)
				t.Errorf("expected kCaFile %q, got %q", tt.kCaFile, settings.KubeCaFile)
				                                           ^
pkg/registry/client.go:331:16: errorf: should replace errors.New(fmt.Sprintf(...)) with fmt.Errorf(...) (revive)
			return nil, errors.New(
				fmt.Sprintf("manifest does not contain a layer with mediatype %s",
					ProvLayerMediaType))
make: *** [test-style] Error 1


$ make test-style

GO111MODULE=on golangci-lint run
pkg/uploader/chart_uploader.go:49:10: errorf: should replace errors.New(fmt.Sprintf(...)) with fmt.Errorf(...) (revive)
		return errors.New(fmt.Sprintf("scheme prefix missing from remote (e.g. \"%s://\")", registry.OCIScheme))
		       ^
cmd/helm/repo_update.go:136:10: errorf: should replace errors.New(fmt.Sprintf(...)) with fmt.Errorf(...) (revive)
		return errors.New(fmt.Sprintf("Failed to update the following repositories: %s",
			repoFailList))
cmd/helm/load_plugins.go:316:16: errorf: should replace errors.New(fmt.Sprintf(...)) with fmt.Errorf(...) (revive)
		return cmds, errors.New(fmt.Sprintf("File (%s) not provided by plugin. No plugin auto-completion possible.", path))
		             ^
make: *** [test-style] Error 1

$ make test-style

GO111MODULE=on golangci-lint run
cmd/helm/load_plugins.go:316:27: error-strings: error strings should not be capitalized or end with punctuation or a newline (revive)
		return cmds, fmt.Errorf("File (%s) not provided by plugin. No plugin auto-completion possible.", path)
		                        ^
make: *** [test-style] Error 1
```

**If applicable**:
- [ ] this PR contains documentation
- [ ] this PR contains unit tests
- [ ] this PR has been tested for backwards compatibility


hickeyma: @bacongobbler you might want to take a look as you had been reviewing the preceding PR #10206 

Patch:
diff --git a/.circleci/config.yml b/.circleci/config.yml
index f3599607b..7a9c4874d 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -13,7 +13,7 @@ jobs:
 
     environment:
       GOCACHE: "/tmp/go/cache"
-      GOLANGCI_LINT_VERSION: "1.36.0"
+      GOLANGCI_LINT_VERSION: "1.43.0"
 
     steps:
       - checkout
diff --git a/.golangci.yml b/.golangci.yml
index 5c2445711..2807ede34 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -8,12 +8,12 @@ linters:
     - dupl
     - gofmt
     - goimports
-    - golint
     - gosimple
     - govet
     - ineffassign
     - misspell
     - nakedret
+    - revive
     - structcheck
     - unused
     - varcheck
diff --git a/cmd/helm/load_plugins.go b/cmd/helm/load_plugins.go
index 70002b0b0..a97d49a93 100644
--- a/cmd/helm/load_plugins.go
+++ b/cmd/helm/load_plugins.go
@@ -313,7 +313,7 @@ func loadFile(path string) (*pluginCommand, error) {
 	cmds := new(pluginCommand)
 	b, err := ioutil.ReadFile(path)
 	if err != nil {
-		return cmds, errors.New(fmt.Sprintf("File (%s) not provided by plugin. No plugin auto-completion possible.", path))
+		return cmds, fmt.Errorf("file (%s) not provided by plugin. No plugin auto-completion possible", path)
 	}
 
 	err = yaml.Unmarshal(b, cmds)
diff --git a/cmd/helm/repo_update.go b/cmd/helm/repo_update.go
index ae09f9195..27661674c 100644
--- a/cmd/helm/repo_update.go
+++ b/cmd/helm/repo_update.go
@@ -133,8 +133,8 @@ func updateCharts(repos []*repo.ChartRepository, out io.Writer, failOnRepoUpdate
 	wg.Wait()
 
 	if len(repoFailList) > 0 && failOnRepoUpdateFail {
-		return errors.New(fmt.Sprintf("Failed to update the following repositories: %s",
-			repoFailList))
+		return fmt.Errorf("Failed to update the following repositories: %s",
+			repoFailList)
 	}
 
 	fmt.Fprintln(out, "Update Complete. ⎈Happy Helming!⎈")
diff --git a/pkg/chartutil/validate_name.go b/pkg/chartutil/validate_name.go
index 8c45d533b..05c090cb6 100644
--- a/pkg/chartutil/validate_name.go
+++ b/pkg/chartutil/validate_name.go
@@ -40,15 +40,15 @@ var (
 	errMissingName = errors.New("no name provided")
 
 	// errInvalidName indicates that an invalid release name was provided
-	errInvalidName = errors.New(fmt.Sprintf(
+	errInvalidName = fmt.Errorf(
 		"invalid release name, must match regex %s and the length must not be longer than 53",
-		validName.String()))
+		validName.String())
 
 	// errInvalidKubernetesName indicates that the name does not meet the Kubernetes
 	// restrictions on metadata names.
-	errInvalidKubernetesName = errors.New(fmt.Sprintf(
+	errInvalidKubernetesName = fmt.Errorf(
 		"invalid metadata name, must match regex %s and the length must not be longer than 253",
-		validName.String()))
+		validName.String())
 )
 
 const (
diff --git a/pkg/registry/client.go b/pkg/registry/client.go
index 213a9dc49..26aae46a4 100644
--- a/pkg/registry/client.go
+++ b/pkg/registry/client.go
@@ -296,9 +296,8 @@ func (c *Client) Pull(ref string, options ...PullOption) (*PullResult, error) {
 
 	numDescriptors := len(descriptors)
 	if numDescriptors < minNumDescriptors {
-		return nil, errors.New(
-			fmt.Sprintf("manifest does not contain minimum number of descriptors (%d), descriptors found: %d",
-				minNumDescriptors, numDescriptors))
+		return nil, fmt.Errorf("manifest does not contain minimum number of descriptors (%d), descriptors found: %d",
+			minNumDescriptors, numDescriptors)
 	}
 	var configDescriptor *ocispec.Descriptor
 	var chartDescriptor *ocispec.Descriptor
@@ -318,22 +317,19 @@ func (c *Client) Pull(ref string, options ...PullOption) (*PullResult, error) {
 		}
 	}
 	if configDescriptor == nil {
-		return nil, errors.New(
-			fmt.Sprintf("could not load config with mediatype %s", ConfigMediaType))
+		return nil, fmt.Errorf("could not load config with mediatype %s", ConfigMediaType)
 	}
 	if operation.withChart && chartDescriptor == nil {
-		return nil, errors.New(
-			fmt.Sprintf("manifest does not contain a layer with mediatype %s",
-				ChartLayerMediaType))
+		return nil, fmt.Errorf("manifest does not contain a layer with mediatype %s",
+			ChartLayerMediaType)
 	}
 	var provMissing bool
 	if operation.withProv && provDescriptor == nil {
 		if operation.ignoreMissingProv {
 			provMissing = true
 		} else {
-			return nil, errors.New(
-				fmt.Sprintf("manifest does not contain a layer with mediatype %s",
-					ProvLayerMediaType))
+			return nil, fmt.Errorf("manifest does not contain a layer with mediatype %s",
+				ProvLayerMediaType)
 		}
 	}
 	result := &PullResult{
diff --git a/pkg/uploader/chart_uploader.go b/pkg/uploader/chart_uploader.go
index 2aa04937a..d7e940406 100644
--- a/pkg/uploader/chart_uploader.go
+++ b/pkg/uploader/chart_uploader.go
@@ -46,7 +46,7 @@ func (c *ChartUploader) UploadTo(ref, remote string) error {
 	}
 
 	if u.Scheme == "" {
-		return errors.New(fmt.Sprintf("scheme prefix missing from remote (e.g. \"%s://\")", registry.OCIScheme))
+		return fmt.Errorf("scheme prefix missing from remote (e.g. \"%s://\")", registry.OCIScheme)
 	}
 
 	p, err := c.Pushers.ByScheme(u.Scheme)


Test patch:
diff --git a/cmd/helm/completion_test.go b/cmd/helm/completion_test.go
index 6d53616d0..1143d6445 100644
--- a/cmd/helm/completion_test.go
+++ b/cmd/helm/completion_test.go
@@ -47,10 +47,10 @@ func checkFileCompletion(t *testing.T, cmdName string, shouldBePerformed bool) {
 	}
 	if !strings.Contains(out, "ShellCompDirectiveNoFileComp") != shouldBePerformed {
 		if shouldBePerformed {
-			t.Error(fmt.Sprintf("Unexpected directive ShellCompDirectiveNoFileComp when completing '%s'", cmdName))
+			t.Errorf("Unexpected directive ShellCompDirectiveNoFileComp when completing '%s'", cmdName)
 		} else {
 
-			t.Error(fmt.Sprintf("Did not receive directive ShellCompDirectiveNoFileComp when completing '%s'", cmdName))
+			t.Errorf("Did not receive directive ShellCompDirectiveNoFileComp when completing '%s'", cmdName)
 		}
 		t.Log(out)
 	}
diff --git a/pkg/cli/environment_test.go b/pkg/cli/environment_test.go
index 1c3dc815e..d2affa79d 100644
--- a/pkg/cli/environment_test.go
+++ b/pkg/cli/environment_test.go
@@ -51,9 +51,9 @@ func TestEnvSettings(t *testing.T) {
 		ns, kcontext string
 		debug        bool
 		maxhistory   int
-		kAsUser      string
-		kAsGroups    []string
-		kCaFile      string
+		kubeAsUser   string
+		kubeAsGroups []string
+		kubeCaFile   string
 	}{
 		{
 			name:       "defaults",
@@ -61,35 +61,35 @@ func TestEnvSettings(t *testing.T) {
 			maxhistory: defaultMaxHistory,
 		},
 		{
-			name:       "with flags set",
-			args:       "--debug --namespace=myns --kube-as-user=poro --kube-as-group=admins --kube-as-group=teatime --kube-as-group=snackeaters --kube-ca-file=/tmp/ca.crt",
-			ns:         "myns",
-			debug:      true,
-			maxhistory: defaultMaxHistory,
-			kAsUser:    "poro",
-			kAsGroups:  []string{"admins", "teatime", "snackeaters"},
-			kCaFile:    "/tmp/ca.crt",
+			name:         "with flags set",
+			args:         "--debug --namespace=myns --kube-as-user=poro --kube-as-group=admins --kube-as-group=teatime --kube-as-group=snackeaters --kube-ca-file=/tmp/ca.crt",
+			ns:           "myns",
+			debug:        true,
+			maxhistory:   defaultMaxHistory,
+			kubeAsUser:   "poro",
+			kubeAsGroups: []string{"admins", "teatime", "snackeaters"},
+			kubeCaFile:   "/tmp/ca.crt",
 		},
 		{
-			name:       "with envvars set",
-			envvars:    map[string]string{"HELM_DEBUG": "1", "HELM_NAMESPACE": "yourns", "HELM_KUBEASUSER": "pikachu", "HELM_KUBEASGROUPS": ",,,operators,snackeaters,partyanimals", "HELM_MAX_HISTORY": "5", "HELM_KUBECAFILE": "/tmp/ca.crt"},
-			ns:         "yourns",
-			maxhistory: 5,
-			debug:      true,
-			kAsUser:    "pikachu",
-			kAsGroups:  []string{"operators", "snackeaters", "partyanimals"},
-			kCaFile:    "/tmp/ca.crt",
+			name:         "with envvars set",
+			envvars:      map[string]string{"HELM_DEBUG": "1", "HELM_NAMESPACE": "yourns", "HELM_KUBEASUSER": "pikachu", "HELM_KUBEASGROUPS": ",,,operators,snackeaters,partyanimals", "HELM_MAX_HISTORY": "5", "HELM_KUBECAFILE": "/tmp/ca.crt"},
+			ns:           "yourns",
+			maxhistory:   5,
+			debug:        true,
+			kubeAsUser:   "pikachu",
+			kubeAsGroups: []string{"operators", "snackeaters", "partyanimals"},
+			kubeCaFile:   "/tmp/ca.crt",
 		},
 		{
-			name:       "with flags and envvars set",
-			args:       "--debug --namespace=myns --kube-as-user=poro --kube-as-group=admins --kube-as-group=teatime --kube-as-group=snackeaters --kube-ca-file=/my/ca.crt",
-			envvars:    map[string]string{"HELM_DEBUG": "1", "HELM_NAMESPACE": "yourns", "HELM_KUBEASUSER": "pikachu", "HELM_KUBEASGROUPS": ",,,operators,snackeaters,partyanimals", "HELM_MAX_HISTORY": "5", "HELM_KUBECAFILE": "/tmp/ca.crt"},
-			ns:         "myns",
-			debug:      true,
-			maxhistory: 5,
-			kAsUser:    "poro",
-			kAsGroups:  []string{"admins", "teatime", "snackeaters"},
-			kCaFile:    "/my/ca.crt",
+			name:         "with flags and envvars set",
+			args:         "--debug --namespace=myns --kube-as-user=poro --kube-as-group=admins --kube-as-group=teatime --kube-as-group=snackeaters --kube-ca-file=/my/ca.crt",
+			envvars:      map[string]string{"HELM_DEBUG": "1", "HELM_NAMESPACE": "yourns", "HELM_KUBEASUSER": "pikachu", "HELM_KUBEASGROUPS": ",,,operators,snackeaters,partyanimals", "HELM_MAX_HISTORY": "5", "HELM_KUBECAFILE": "/tmp/ca.crt"},
+			ns:           "myns",
+			debug:        true,
+			maxhistory:   5,
+			kubeAsUser:   "poro",
+			kubeAsGroups: []string{"admins", "teatime", "snackeaters"},
+			kubeCaFile:   "/my/ca.crt",
 		},
 	}
 
@@ -119,14 +119,14 @@ func TestEnvSettings(t *testing.T) {
 			if settings.MaxHistory != tt.maxhistory {
 				t.Errorf("expected maxHistory %d, got %d", tt.maxhistory, settings.MaxHistory)
 			}
-			if tt.kAsUser != settings.KubeAsUser {
-				t.Errorf("expected kAsUser %q, got %q", tt.kAsUser, settings.KubeAsUser)
+			if tt.kubeAsUser != settings.KubeAsUser {
+				t.Errorf("expected kAsUser %q, got %q", tt.kubeAsUser, settings.KubeAsUser)
 			}
-			if !reflect.DeepEqual(tt.kAsGroups, settings.KubeAsGroups) {
-				t.Errorf("expected kAsGroups %+v, got %+v", len(tt.kAsGroups), len(settings.KubeAsGroups))
+			if !reflect.DeepEqual(tt.kubeAsGroups, settings.KubeAsGroups) {
+				t.Errorf("expected kAsGroups %+v, got %+v", len(tt.kubeAsGroups), len(settings.KubeAsGroups))
 			}
-			if tt.kCaFile != settings.KubeCaFile {
-				t.Errorf("expected kCaFile %q, got %q", tt.kCaFile, settings.KubeCaFile)
+			if tt.kubeCaFile != settings.KubeCaFile {
+				t.Errorf("expected kCaFile %q, got %q", tt.kubeCaFile, settings.KubeCaFile)
 			}
 		})
 	}