From 35c285dd4f7eb82ce65b055394326c8f349cd250 Mon Sep 17 00:00:00 2001 From: DTLP Date: Wed, 21 Oct 2026 16:50:36 +0100 Subject: [PATCH] Upd golangci-lint to v2.15.0 and migrate config --- .golangci.yml | 159 +++++++++++++++---------------------- Dockerfile | 6 +- Makefile | 7 +- cmd/sql-backup/cmd_test.go | 5 +- internal/dbcli/cli.go | 12 +-- 5 files changed, 80 insertions(+), 109 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index a48f2ef..c7cc5ee 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,108 +1,79 @@ -# options for analysis running +version: "2" + run: - deadline: 20s tests: true - skip-dirs: - - contract - skip-files: - - ".*\\.pb\\.go" - - "\\.\\./\\.\\./.*" - silent: true - -# output configuration options -output: - format: colored-line-number - print-issued-lines: true - print-linter-name: true - -# all available settings of specific linters -linters-settings: - errcheck: - check-type-assertions: true - check-blank: true - govet: - check-shadowing: true - gofmt: - simplify: true - goconst: - min-len: 3 - min-occurrences: 3 - misspell: - locale: UK - unused: - check-exported: false - unparam: - algo: cha - nakedret: - max-func-lines: 30 - prealloc: - simple: true - range-loops: true - for-loops: true linters: + default: none enable: - - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification [fast: true] - - misspell # Finds commonly misspelled English words in comments [fast: true] - - nakedret # Finds naked returns in functions greater than a specified function length [fast: true] - - errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases [fast: false] - - staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks [fast: false] - - unused # Checks Go code for unused constants, variables, functions and types [fast: false] - - gas # Inspects source code for security problems [fast: false] - - unconvert # Remove unnecessary type conversions [fast: false] - - unparam # Reports unused function parameters [fast: false] + - misspell + - nakedret + - errcheck + - govet + - ineffassign + - staticcheck + - unused + - gosec + - unconvert + - unparam + settings: + errcheck: + check-type-assertions: true + check-blank: true + govet: + enable: + - shadow + misspell: + locale: UK + nakedret: + max-func-lines: 30 + staticcheck: + # v2 merges gosimple (S) and stylecheck (ST) into staticcheck. v1 had + # gosimple disabled and stylecheck not enabled, so keep only the SA checks. + checks: ["all", "-S*", "-ST*"] - disable: - - golint # Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes [fast: true] - - structcheck # Finds an unused struct fields [fast: false] - - interfacer # Linter that suggests narrower interface types [fast: false] - - prealloc # Finds slice declarations that could potentially be preallocated [fast: true] - - lll # Reports long lines [fast: true] - - dupl # Tool for code clone detection [fast: true] - - typecheck # Like the front-end of a Go compiler, parses and type-checks Go code [fast: false] - - depguard # Go linter that checks if package imports are in a list of acceptable packages [fast: false] - - varcheck # Finds unused global variables and constants [fast: false] - - deadcode # Finds unused code [fast: false] - - gosimple # Linter for Go source code that specializes in simplifying a code [fast: false] - - goconst # Finds repeated strings that could be replaced by a constant [fast: true] - - gocyclo # Computes and checks the cyclomatic complexity of functions [fast: true] - - maligned # Tool to detect Go structs that would take less memory if their fields were sorted [fast: false] - - megacheck # 3 sub-linters in one: unused, gosimple and staticcheck [fast: false] - - goimports # Goimports does everything that gofmt does. Additionally it checks unused imports [fast: true] + exclusions: + # v1 had exclude-use-default: false + presets: [] + paths: + - contract + - '\.pb\.go' + rules: + # errcheck: Almost all programs ignore errors on these functions and in most cases it's ok + - linters: [errcheck] + text: Error return value of .((os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*printf?|os\.(Un)?Setenv). is not checked -issues: - exclude-use-default: false - exclude: - # errcheck: Almost all programs ignore errors on these functions and in most cases it's ok - - Error return value of - .((os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*printf?|os\.(Un)?Setenv). - is not checked + # gosec: Too many false-positives on 'unsafe' usage + - linters: [gosec] + text: Use of unsafe calls should be audited - # golint: Exported variables are rarely used and generally reserved for errors which should be self explanitory - - exported var \w+ should have comment or be unexported + # gosec: Too many false-positives for parametrized shell calls + - linters: [gosec] + text: Subprocess launch(ed with variable|ing should be audited) - # golint: False positive when tests are defined in package 'test' - - func name will be used as test\.Test.* by other packages, and that - stutters; consider calling this + # gosec: Duplicated errcheck checks + - linters: [gosec] + text: G104 - # gas: Too many false-positives on 'unsafe' usage - - Use of unsafe calls should be audited + # gosec: Too many issues in popular repos + - linters: [gosec] + text: (Expect directory permissions to be 0750 or less|Expect file permissions to be 0600 or less) - # gas: Too many false-positives for parametrized shell calls - - Subprocess launch(ed with variable|ing should be audited) + # gosec: False positive is triggered by 'src, err := ioutil.ReadFile(filename)' + - linters: [gosec] + text: Potential file inclusion via variable - # gas: Duplicated errcheck checks - - G104 + # govet: Common false positives + - linters: [govet] + text: (possible misuse of unsafe.Pointer|should have signature) - # gas: Too many issues in popular repos - - (Expect directory permissions to be 0750 or less|Expect file permissions - to be 0600 or less) + # staticcheck: Developers tend to write in C-style with an explicit 'break' in a 'switch', so it's ok to ignore + - linters: [staticcheck] + text: ineffective break statement. Did you mean to break out of the outer loop - # gas: False positive is triggered by 'src, err := ioutil.ReadFile(filename)' - - Potential file inclusion via variable - - # govet: Common false positives - - (possible misuse of unsafe.Pointer|should have signature) - - # megacheck: Developers tend to write in C-style with an explicit 'break' in a 'switch', so it's ok to ignore - - ineffective break statement. Did you mean to break out of the outer loop \ No newline at end of file +formatters: + enable: + - gofmt + settings: + gofmt: + simplify: true diff --git a/Dockerfile b/Dockerfile index c306f8f..3c91c17 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,15 +3,15 @@ FROM golang:1.27-alpine AS build COPY . /go/src/github.com/utilitywarehouse/sql-backup WORKDIR /go/src/github.com/utilitywarehouse/sql-backup -ENV GOLANGCI_LINT_VERSION="v1.59.1" +ENV GOLANGCI_LINT_VERSION="v2.15.0" # GOTOOLCHAIN pins the exact toolchain declared by go.mod's `go` line, so the # build isn't at the mercy of whatever patch version the base image ships. RUN apk --no-cache add make build-base git ca-certificates && \ - GOTOOLCHAIN=go$(awk '/^go /{print $2; exit}' go.mod) && \ + export GOTOOLCHAIN=go$(awk '/^go /{print $2; exit}' go.mod) && \ go mod download && \ go test -v -cover -p=1 ./... && \ - wget -O- -nv https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s ${GOLANGCI_LINT_VERSION} && \ + wget -O- -nv https://raw.githubusercontent.com/golangci/golangci-lint/${GOLANGCI_LINT_VERSION}/install.sh | sh -s ${GOLANGCI_LINT_VERSION} && \ ./bin/golangci-lint run && \ go build -o /sql-backup \ -ldflags "\ diff --git a/Makefile b/Makefile index a2e5a26..7f5f07a 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,8 @@ LINKFLAGS := -s -w -X main.gitHash=$(GIT_HASH) -extldflags "-static" LINTFLAGS := --timeout=10m TESTFLAGS := -v -cover LINTER := golangci-lint +# Single source of truth for the version is the Dockerfile. +LINTER_VERSION := $(shell sed -n 's/^ENV GOLANGCI_LINT_VERSION="\(.*\)"/\1/p' Dockerfile) EMPTY := SPACE := $(EMPTY) $(EMPTY) @@ -29,7 +31,10 @@ install: @GO111MODULE=on GOPRIVATE="github.com/utilitywarehouse/*" go mod download $(LINTER): - @[ -e ./bin/$(LINTER) ] || wget -O - -q https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s latest + @test -n "$(LINTER_VERSION)" || { echo "GOLANGCI_LINT_VERSION not found in Dockerfile" >&2; exit 1; } + @if ! ./bin/$(LINTER) version 2>/dev/null | grep -qwF "$(LINTER_VERSION:v%=%)"; then \ + wget -O - -q https://raw.githubusercontent.com/golangci/golangci-lint/$(LINTER_VERSION)/install.sh | sh -s $(LINTER_VERSION); \ + fi .PHONY: lint lint: $(LINTER) diff --git a/cmd/sql-backup/cmd_test.go b/cmd/sql-backup/cmd_test.go index 9842a20..bf2ff63 100644 --- a/cmd/sql-backup/cmd_test.go +++ b/cmd/sql-backup/cmd_test.go @@ -2,7 +2,6 @@ package main import ( "flag" - "io/ioutil" "os" "testing" "time" @@ -96,7 +95,7 @@ func TestDumperFromFlags_InvalidBinaryPath(t *testing.T) { } func TestDumperFromFlags_ValidBinaryPath(t *testing.T) { - f, err := ioutil.TempFile("", "TestDumperFromFlags_ValidBinaryPath") + f, err := os.CreateTemp("", "TestDumperFromFlags_ValidBinaryPath") if err != nil { t.Fatal(err) } @@ -118,7 +117,7 @@ func TestDumperFromFlags_ValidBinaryPath(t *testing.T) { } func TestDumperFromFlags_Timeout(t *testing.T) { - f, err := ioutil.TempFile("", "TestDumperFromFlags_ValidBinaryPath") + f, err := os.CreateTemp("", "TestDumperFromFlags_ValidBinaryPath") if err != nil { t.Fatal(err) } diff --git a/internal/dbcli/cli.go b/internal/dbcli/cli.go index 244db9b..45e2629 100644 --- a/internal/dbcli/cli.go +++ b/internal/dbcli/cli.go @@ -67,11 +67,7 @@ func (d CliDumper) Dump(ctx context.Context, db string, w io.Writer) error { return ctx.Err() } - // Not checking error as was checked in NewDumper - cmdPath, _ := exec.LookPath(d.Cmd) // nolint:errcheck - - // #nosec G204 - dumpCmd := exec.Command(cmdPath, "dump", db, d.Flags) + var dumpCmd *exec.Cmd switch d.Cmd { case "pg_dump": u, err := dsnToURL(d.DSN) @@ -114,17 +110,17 @@ func (d CliDumper) Dump(ctx context.Context, db string, w io.Writer) error { select { case <-ctx.Done(): if err := dumpCmd.Process.Kill(); err != nil { - <-doneCh // wait for the command to terminate + <-doneCh //nolint:errcheck // wait for exit; result irrelevant } return errors.Wrap(ctx.Err(), "context was cancelled") case <-timeoutCh: if err := dumpCmd.Process.Kill(); err != nil { - <-doneCh // wait for the command to terminate + <-doneCh //nolint:errcheck // wait for exit; result irrelevant } return fmt.Errorf("timed out dumping database: %s", db) case err := <-doneCh: if err != nil { - log.WithField("db", db).WithError(err).Error(string(errBuff.Bytes())) + log.WithField("db", db).WithError(err).Error(errBuff.String()) return errors.Wrap(err, "dumper failed") } return buf.Flush()