diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2cd97612..f6f7bbef 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -128,7 +128,7 @@ jobs: go version - name: GolangCI-Lint - uses: golangci/golangci-lint-action@v6 + uses: golangci/golangci-lint-action@v7 with: version: latest diff --git a/.golangci.yml b/.golangci.yml index fe6a6938..135f4422 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,18 +1,30 @@ +version: "2" linters: enable: - gocyclo - misspell - revive - -linters-settings: - gocyclo: - # minimal code complexity to report, 30 by default (but we recommend 10-20) - min-complexity: 15 - -issues: - # List of regexps of issue texts to exclude, empty list by default. - # But independently from this option we use default exclude patterns, - # it can be disabled by `exclude-use-default: false`. To list all - # excluded by default patterns execute `golangci-lint run --help` - exclude: - - SA5008 # ignore staticcheck for go-flags \ No newline at end of file + settings: + gocyclo: + min-complexity: 15 + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + rules: + - path: (.+)\.go$ + text: SA5008 # ignore staticcheck for go-flags + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/internal/config/config.go b/internal/config/config.go index 0c165378..0e206d23 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -53,22 +53,22 @@ func eachOption(g *flags.Group, f func(*flags.Group, *flags.Option)) { // VisitAll will execute fn() for all options found in command line. // Since we have only two level of nesting it's enough to use simplified group-prefixed name. func (cmdSet cmdArgSet) VisitAll(fn func(viper.FlagValue)) { - root := cmdSet.Parser.Group.Find("Application Options") + root := cmdSet.Group.Find("Application Options") eachOption(root, func(g *flags.Group, o *flags.Option) { name := o.LongName if g != root { - name = g.ShortDescription + cmdSet.Parser.NamespaceDelimiter + name + name = g.ShortDescription + cmdSet.NamespaceDelimiter + name } fn(cmdArg{name, o}) }) } func (cmdSet cmdArgSet) setDefaults(v *viper.Viper) { - eachOption(cmdSet.Parser.Group, func(g *flags.Group, o *flags.Option) { + eachOption(cmdSet.Group, func(g *flags.Group, o *flags.Option) { if o.Default != nil && o.IsSetDefault() { name := o.LongName - if g != cmdSet.Parser.Group { - name = g.ShortDescription + cmdSet.Parser.NamespaceDelimiter + name + if g != cmdSet.Group { + name = g.ShortDescription + cmdSet.NamespaceDelimiter + name } v.SetDefault(name, o.Value()) } @@ -91,12 +91,12 @@ func NewConfig(writer io.Writer) (*CmdOptions, error) { v.SetConfigFile(v.GetString("config")) err := v.ReadInConfig() // Find and read the config file if err != nil { // Handle errors reading the config file - return nil, fmt.Errorf("Fatal error reading config file: %w", err) + return nil, fmt.Errorf("fatal error reading config file: %w", err) } } conf := &CmdOptions{} if err = v.Unmarshal(conf); err != nil { - return nil, fmt.Errorf("Fatal error unmarshalling config file: %w", err) + return nil, fmt.Errorf("fatal error unmarshalling config file: %w", err) } if conf.ClientName == "" { buf := bytes.NewBufferString("The required flag `-c, --clientname` was not specified\n") diff --git a/internal/pgengine/bootstrap.go b/internal/pgengine/bootstrap.go index 7ea631bd..ebc999d7 100644 --- a/internal/pgengine/bootstrap.go +++ b/internal/pgengine/bootstrap.go @@ -135,7 +135,7 @@ func NewDB(DB PgxPoolIface, args ...string) *PgEngine { } func quoteIdent(s string) string { - return `"` + strings.Replace(s, `"`, `""`, -1) + `"` + return `"` + strings.ReplaceAll(s, `"`, `""`) + `"` } // getPgxConnConfig transforms standard connestion string to pgx specific one with @@ -230,7 +230,7 @@ func (pge *PgEngine) TryLockClientName(ctx context.Context, conn QueryRowIface) if e := conn.QueryRow(ctx, sql, pge.Getsid(), pge.ClientName).Scan(&locked); e != nil { return e } else if !locked { - return errors.New("Cannot obtain lock for a session") + return errors.New("cannot obtain lock for a session") } return nil } @@ -240,12 +240,12 @@ func (pge *PgEngine) ExecuteCustomScripts(ctx context.Context, filename ...strin for _, f := range filename { sql, err := os.ReadFile(f) if err != nil { - pge.l.WithError(err).Error("Cannot read command file") + pge.l.WithError(err).Error("cannot read command file") return err } pge.l.Info("Executing script: ", f) if _, err = pge.ConfigDb.Exec(ctx, string(sql)); err != nil { - pge.l.WithError(err).Error("Script execution failed") + pge.l.WithError(err).Error("script execution failed") return err } pge.l.Info("Script file executed: ", f) diff --git a/internal/pgengine/notification.go b/internal/pgengine/notification.go index 71bcf0d2..93e8996a 100644 --- a/internal/pgengine/notification.go +++ b/internal/pgengine/notification.go @@ -63,12 +63,12 @@ func (pge *PgEngine) NotificationHandler(c *pgconn.PgConn, n *pgconn.Notificatio pge.chainSignalChan <- signal return } - err = fmt.Errorf("Unknown chain ID: %d", signal.ConfigID) + err = fmt.Errorf("unknown chain ID: %d", signal.ConfigID) default: - err = fmt.Errorf("Unknown command: %s", signal.Command) + err = fmt.Errorf("unknown command: %s", signal.Command) } } - l.WithError(err).Error("Syntax error in payload") + l.WithError(err).Error("syntax error in payload") } // WaitForChainSignal returns configuration id from the notifications diff --git a/internal/scheduler/chain.go b/internal/scheduler/chain.go index 2faa092d..a71ae401 100644 --- a/internal/scheduler/chain.go +++ b/internal/scheduler/chain.go @@ -62,7 +62,7 @@ func (sch *Scheduler) processAsyncChain(ctx context.Context, chainSignal ChainSi case "START": var c Chain if err := sch.pgengine.SelectChain(ctx, &c, chainSignal.ConfigID); err != nil { - return fmt.Errorf("Cannot start chain with ID: %d; %w", chainSignal.ConfigID, err) + return fmt.Errorf("cannot start chain with ID: %d; %w", chainSignal.ConfigID, err) } go func() { select { @@ -77,7 +77,7 @@ func (sch *Scheduler) processAsyncChain(ctx context.Context, chainSignal ChainSi cancel() return nil } - return fmt.Errorf("Cannot stop chain with ID: %d. No running chain found", chainSignal.ConfigID) + return fmt.Errorf("cannot stop chain with ID: %d. No running chain found", chainSignal.ConfigID) } return nil } diff --git a/internal/scheduler/shell.go b/internal/scheduler/shell.go index 0700badb..b31781e0 100644 --- a/internal/scheduler/shell.go +++ b/internal/scheduler/shell.go @@ -30,7 +30,7 @@ func (sch *Scheduler) ExecuteProgramCommand(ctx context.Context, command string, command = strings.TrimSpace(command) if command == "" { - return -1, "", errors.New("Program command cannot be empty") + return -1, "", errors.New("program command cannot be empty") } if len(paramValues) == 0 { //mimic empty param paramValues = []string{""} @@ -50,7 +50,7 @@ func (sch *Scheduler) ExecuteProgramCommand(ctx context.Context, command string, if err != nil { //check if we're dealing with an ExitError - i.e. return code other than 0 if exitError, ok := err.(*exec.ExitError); ok { - exitCode := exitError.ProcessState.ExitCode() + exitCode := exitError.ExitCode() l.WithField("retcode", exitCode).Debug("Program run", cmdLine, exitCode) return exitCode, stdout, exitError } diff --git a/internal/scheduler/shell_test.go b/internal/scheduler/shell_test.go index fd106b39..c2d8c454 100644 --- a/internal/scheduler/shell_test.go +++ b/internal/scheduler/shell_test.go @@ -39,7 +39,7 @@ func TestShellCommand(t *testing.T) { ctx := context.Background() _, _, err = scheduler.ExecuteProgramCommand(ctx, "", []string{""}) - assert.EqualError(t, err, "Program command cannot be empty", "Empty command should out, fail") + assert.EqualError(t, err, "program command cannot be empty", "Empty command should out, fail") _, out, err = scheduler.ExecuteProgramCommand(ctx, "ping0", nil) assert.NoError(t, err, "Command with nil param is out, OK") diff --git a/internal/scheduler/tasks.go b/internal/scheduler/tasks.go index cfa27ec3..19ed5c77 100644 --- a/internal/scheduler/tasks.go +++ b/internal/scheduler/tasks.go @@ -117,7 +117,7 @@ func taskDownload(ctx context.Context, _ *Scheduler, paramValues string) (stdout return "", err } if len(opts.FileUrls) == 0 { - return "", errors.New("Files to download are not specified") + return "", errors.New("files to download are not specified") } return tasks.DownloadUrls(ctx, opts.FileUrls, opts.DestPath, opts.WorkersNum) } diff --git a/internal/scheduler/tasks_test.go b/internal/scheduler/tasks_test.go index b2ba89eb..94ac8ada 100644 --- a/internal/scheduler/tasks_test.go +++ b/internal/scheduler/tasks_test.go @@ -43,7 +43,7 @@ func TestExecuteTask(t *testing.T) { assert.Error(t, et("Download", []string{"foo"}), "Invalid json") assert.EqualError(t, et("Download", []string{`{"workersnum": 0, "fileurls": [] }`}), - "Files to download are not specified", "Download with empty files should fail") + "files to download are not specified", "Download with empty files should fail") assert.Error(t, et("Download", []string{`{"workersnum": 0, "fileurls": ["http://foo.bar"], "destpath": "" }`}), "Downlod incorrect url should fail")