From b74428d80e5a20324dd0f26cc286116e7fbc6e9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Thu, 27 Mar 2025 00:44:15 +0200 Subject: [PATCH 1/3] chore(golangci-lint): upgrade to v2 --- .github/workflows/test.yml | 2 +- .golangci.yml | 23 ++++++++++------------- command_test.go | 2 +- completions_test.go | 2 +- 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2904bf0e4..f6a3111bc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -47,7 +47,7 @@ jobs: check-latest: true cache: true - - uses: golangci/golangci-lint-action@v4.0.0 + - uses: golangci/golangci-lint-action@v8.0.0 with: version: latest args: --verbose diff --git a/.golangci.yml b/.golangci.yml index 2c8f4808c..71688aa34 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -12,14 +12,20 @@ # See the License for the specific language governing permissions and # limitations under the License. +version: "2" + run: - deadline: 5m + timeout: 5m + +formatters: + enable: + - gofmt + - goimports linters: - disable-all: true + default: none enable: #- bodyclose - # - deadcode ! deprecated since v1.49.0; replaced by 'unused' #- depguard #- dogsled #- dupl @@ -30,28 +36,19 @@ linters: - goconst - gocritic #- gocyclo - - gofmt - - goimports - #- gomnd #- goprintffuncname - gosec - - gosimple - govet - ineffassign #- lll - misspell + #- mnd #- nakedret #- noctx - nolintlint #- rowserrcheck - #- scopelint - staticcheck - #- structcheck ! deprecated since v1.49.0; replaced by 'unused' - - stylecheck - #- typecheck - unconvert #- unparam - unused - # - varcheck ! deprecated since v1.49.0; replaced by 'unused' #- whitespace - fast: false diff --git a/command_test.go b/command_test.go index 156df9eb6..a86e57f0a 100644 --- a/command_test.go +++ b/command_test.go @@ -2926,7 +2926,7 @@ func TestHelpFuncExecuted(t *testing.T) { helpText := "Long description" // Create a context that will be unique, not just the background context - //nolint:golint,staticcheck // We can safely use a basic type as key in tests. + //nolint:staticcheck // We can safely use a basic type as key in tests. executionCtx := context.WithValue(context.Background(), "testKey", "123") child := &Command{Use: "child", Run: emptyRun} diff --git a/completions_test.go b/completions_test.go index 89da3d509..71c0d1ff6 100644 --- a/completions_test.go +++ b/completions_test.go @@ -1297,7 +1297,7 @@ func TestValidArgsFuncCmdContext(t *testing.T) { } rootCmd.AddCommand(childCmd) - //nolint:golint,staticcheck // We can safely use a basic type as key in tests. + //nolint:staticcheck // We can safely use a basic type as key in tests. ctx := context.WithValue(context.Background(), "testKey", "123") // Test completing an empty string on the childCmd From a6eb57a9ca16f958a0337f6f913113b31d355590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Thu, 27 Mar 2025 00:45:29 +0200 Subject: [PATCH 2/3] refactor: apply golangci-lint autofixes, work around false positives --- completions.go | 4 ++-- completions_test.go | 11 +++++------ doc/man_docs.go | 4 ++-- doc/md_docs.go | 8 ++++---- doc/rest_docs.go | 8 ++++---- doc/yaml_docs.go | 2 +- 6 files changed, 18 insertions(+), 19 deletions(-) diff --git a/completions.go b/completions.go index a1752f763..db62808e2 100644 --- a/completions.go +++ b/completions.go @@ -375,7 +375,7 @@ func (c *Command) getCompletions(args []string) (*Command, []Completion, ShellCo // Error while attempting to parse flags if flagErr != nil { // If error type is flagCompError and we don't want flagCompletion we should ignore the error - if _, ok := flagErr.(*flagCompError); !(ok && !flagCompletion) { + if _, ok := flagErr.(*flagCompError); !ok || flagCompletion { return finalCmd, []Completion{}, ShellCompDirectiveDefault, flagErr } } @@ -773,7 +773,7 @@ See each sub-command's help for details on how to use the generated script. // shell completion for it (prog __complete completion '') subCmd, cmdArgs, err := c.Find(args) if err != nil || subCmd.Name() != compCmdName && - !(subCmd.Name() == ShellCompRequestCmd && len(cmdArgs) > 1 && cmdArgs[0] == compCmdName) { + (subCmd.Name() != ShellCompRequestCmd || len(cmdArgs) <= 1 || cmdArgs[0] != compCmdName) { // The completion command is not being called or being completed so we remove it. c.RemoveCommand(completionCmd) return diff --git a/completions_test.go b/completions_test.go index 71c0d1ff6..1f6d5c288 100644 --- a/completions_test.go +++ b/completions_test.go @@ -2899,7 +2899,7 @@ func TestCompletionFuncCompatibility(t *testing.T) { var userComp func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) // check against new signature - var _ CompletionFunc = userComp + var _ CompletionFunc = userComp //nolint:staticcheck // LHS type is needed for this use case // check Command accepts cmd := Command{ @@ -2913,8 +2913,7 @@ func TestCompletionFuncCompatibility(t *testing.T) { var userComp func(cmd *Command, args []string, toComplete string) ([]Completion, ShellCompDirective) // check against new signature - var _ CompletionFunc = userComp - + var _ CompletionFunc = userComp //nolint:staticcheck // LHS type is needed for this use case // check Command accepts cmd := Command{ ValidArgsFunction: userComp, @@ -2927,8 +2926,8 @@ func TestCompletionFuncCompatibility(t *testing.T) { var userComp CompletionFunc // check helper against old signature - var _ func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) = userComp - var _ func(cmd *Command, args []string, toComplete string) ([]Completion, ShellCompDirective) = userComp + var _ func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) = userComp //nolint:staticcheck // LHS type is needed for this use case + var _ func(cmd *Command, args []string, toComplete string) ([]Completion, ShellCompDirective) = userComp //nolint:staticcheck // LHS type is needed for this use case // check Command accepts cmd := Command{ @@ -2967,7 +2966,7 @@ func TestCompletionFuncCompatibility(t *testing.T) { var userComp UserCompletionTypeAliasHelper // Here we are validating the existing type validates the CompletionFunc type - var _ CompletionFunc = userComp + var _ CompletionFunc = userComp //nolint:staticcheck // LHS type is needed for this use case cmd := Command{ ValidArgsFunction: userComp, diff --git a/doc/man_docs.go b/doc/man_docs.go index 2138f2488..560bc20c7 100644 --- a/doc/man_docs.go +++ b/doc/man_docs.go @@ -212,7 +212,7 @@ func genMan(cmd *cobra.Command, header *GenManHeader) []byte { manPrintOptions(buf, cmd) if len(cmd.Example) > 0 { buf.WriteString("# EXAMPLE\n") - buf.WriteString(fmt.Sprintf("```\n%s\n```\n", cmd.Example)) + fmt.Fprintf(buf, "```\n%s\n```\n", cmd.Example) } if hasSeeAlso(cmd) { buf.WriteString("# SEE ALSO\n") @@ -240,7 +240,7 @@ func genMan(cmd *cobra.Command, header *GenManHeader) []byte { buf.WriteString(strings.Join(seealsos, ", ") + "\n") } if !cmd.DisableAutoGenTag { - buf.WriteString(fmt.Sprintf("# HISTORY\n%s Auto generated by spf13/cobra\n", header.Date.Format("2-Jan-2006"))) + fmt.Fprintf(buf, "# HISTORY\n%s Auto generated by spf13/cobra\n", header.Date.Format("2-Jan-2006")) } return buf.Bytes() } diff --git a/doc/md_docs.go b/doc/md_docs.go index 12592223b..6eae7ccfb 100644 --- a/doc/md_docs.go +++ b/doc/md_docs.go @@ -69,12 +69,12 @@ func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) } if cmd.Runnable() { - buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.UseLine())) + fmt.Fprintf(buf, "```\n%s\n```\n\n", cmd.UseLine()) } if len(cmd.Example) > 0 { buf.WriteString("### Examples\n\n") - buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.Example)) + fmt.Fprintf(buf, "```\n%s\n```\n\n", cmd.Example) } if err := printOptions(buf, cmd, name); err != nil { @@ -87,7 +87,7 @@ func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) pname := parent.CommandPath() link := pname + markdownExtension link = strings.ReplaceAll(link, " ", "_") - buf.WriteString(fmt.Sprintf("* [%s](%s)\t - %s\n", pname, linkHandler(link), parent.Short)) + fmt.Fprintf(buf, "* [%s](%s)\t - %s\n", pname, linkHandler(link), parent.Short) cmd.VisitParents(func(c *cobra.Command) { if c.DisableAutoGenTag { cmd.DisableAutoGenTag = c.DisableAutoGenTag @@ -105,7 +105,7 @@ func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) cname := name + " " + child.Name() link := cname + markdownExtension link = strings.ReplaceAll(link, " ", "_") - buf.WriteString(fmt.Sprintf("* [%s](%s)\t - %s\n", cname, linkHandler(link), child.Short)) + fmt.Fprintf(buf, "* [%s](%s)\t - %s\n", cname, linkHandler(link), child.Short) } buf.WriteString("\n") } diff --git a/doc/rest_docs.go b/doc/rest_docs.go index c33acc2ba..4901ca980 100644 --- a/doc/rest_docs.go +++ b/doc/rest_docs.go @@ -82,13 +82,13 @@ func GenReSTCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string, str buf.WriteString("\n" + long + "\n\n") if cmd.Runnable() { - buf.WriteString(fmt.Sprintf("::\n\n %s\n\n", cmd.UseLine())) + fmt.Fprintf(buf, "::\n\n %s\n\n", cmd.UseLine()) } if len(cmd.Example) > 0 { buf.WriteString("Examples\n") buf.WriteString("~~~~~~~~\n\n") - buf.WriteString(fmt.Sprintf("::\n\n%s\n\n", indentString(cmd.Example, " "))) + fmt.Fprintf(buf, "::\n\n%s\n\n", indentString(cmd.Example, " ")) } if err := printOptionsReST(buf, cmd, name); err != nil { @@ -101,7 +101,7 @@ func GenReSTCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string, str parent := cmd.Parent() pname := parent.CommandPath() ref = strings.ReplaceAll(pname, " ", "_") - buf.WriteString(fmt.Sprintf("* %s \t - %s\n", linkHandler(pname, ref), parent.Short)) + fmt.Fprintf(buf, "* %s \t - %s\n", linkHandler(pname, ref), parent.Short) cmd.VisitParents(func(c *cobra.Command) { if c.DisableAutoGenTag { cmd.DisableAutoGenTag = c.DisableAutoGenTag @@ -118,7 +118,7 @@ func GenReSTCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string, str } cname := name + " " + child.Name() ref = strings.ReplaceAll(cname, " ", "_") - buf.WriteString(fmt.Sprintf("* %s \t - %s\n", linkHandler(cname, ref), child.Short)) + fmt.Fprintf(buf, "* %s \t - %s\n", linkHandler(cname, ref), child.Short) } buf.WriteString("\n") } diff --git a/doc/yaml_docs.go b/doc/yaml_docs.go index 2b26d6ec0..371971703 100644 --- a/doc/yaml_docs.go +++ b/doc/yaml_docs.go @@ -153,7 +153,7 @@ func genFlagResult(flags *pflag.FlagSet) []cmdOption { // Todo, when we mark a shorthand is deprecated, but specify an empty message. // The flag.ShorthandDeprecated is empty as the shorthand is deprecated. // Using len(flag.ShorthandDeprecated) > 0 can't handle this, others are ok. - if !(len(flag.ShorthandDeprecated) > 0) && len(flag.Shorthand) > 0 { + if len(flag.ShorthandDeprecated) == 0 && len(flag.Shorthand) > 0 { opt := cmdOption{ flag.Name, flag.Shorthand, From 6680892c5c8abc22d39ac8b273e0f2f0b6784440 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Wed, 28 May 2025 22:35:15 +0300 Subject: [PATCH 3/3] chore(golangci-lint): add some exclusion presets To avoid cropping up new findings for commonly ignored issues for now. --- .golangci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.golangci.yml b/.golangci.yml index 71688aa34..6acf8ab1e 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -52,3 +52,8 @@ linters: #- unparam - unused #- whitespace + exclusions: + presets: + - common-false-positives + - legacy + - std-error-handling