Merge pull request #1460 from crazy-max/golangci-lint-v2

update golangci-lint to v2.1.6
This commit is contained in:
CrazyMax
2025-08-03 20:25:06 +02:00
committed by GitHub
14 changed files with 170 additions and 117 deletions

View File

@@ -1,12 +1,11 @@
version: "2"
run: run:
timeout: 30m modules-download-mode: vendor
build-tags: build-tags:
- containers_image_openpgp - containers_image_openpgp
- exclude_graphdriver_btrfs - exclude_graphdriver_btrfs
- exclude_graphdriver_devicemapper - exclude_graphdriver_devicemapper
# default uses Go version from the go.mod file, fallback on the env var
# `GOVERSION`, fallback on 1.17: https://golangci-lint.run/usage/configuration/#run-configuration
go: "1.23"
linters: linters:
enable: enable:
@@ -14,10 +13,7 @@ linters:
- depguard - depguard
- forbidigo - forbidigo
- gocritic - gocritic
- gofmt
- goimports
- gosec - gosec
- gosimple
- govet - govet
- ineffassign - ineffassign
- makezero - makezero
@@ -27,79 +23,102 @@ linters:
- revive - revive
- staticcheck - staticcheck
- testifylint - testifylint
- typecheck
- unused - unused
- whitespace - whitespace
disable-all: true settings:
gocritic:
linters-settings: disabled-checks:
gocritic: - "ifElseChain"
disabled-checks: - "assignOp"
- "ifElseChain" - "appendAssign"
- "assignOp" - "singleCaseSwitch"
- "appendAssign" importas:
- "singleCaseSwitch" alias:
- "exitAfterDefer" # FIXME - pkg: "github.com/opencontainers/image-spec/specs-go/v1"
importas: alias: "ocispecs"
alias: - pkg: "github.com/opencontainers/go-digest"
- pkg: "github.com/opencontainers/image-spec/specs-go/v1" alias: "digest"
alias: "ocispecs" govet:
- pkg: "github.com/opencontainers/go-digest" enable:
alias: "digest" - nilness
govet: - unusedwrite
enable: depguard:
- nilness rules:
- unusedwrite main:
depguard: deny:
- pkg: "github.com/containerd/containerd/errdefs"
desc: The containerd errdefs package was migrated to a separate module. Use github.com/containerd/errdefs instead.
- pkg: "github.com/containerd/containerd/log"
desc: The containerd log package was migrated to a separate module. Use github.com/containerd/log instead.
- pkg: "github.com/containerd/containerd/platforms"
desc: The containerd platforms package was migrated to a separate module. Use github.com/containerd/platforms instead.
- pkg: "io/ioutil"
desc: The io/ioutil package has been deprecated.
forbidigo:
forbid:
- pattern: ^context\.WithCancel(# use context\.WithCancelCause instead)?$
- pattern: ^context\.WithDeadline(# use context\.WithDeadline instead)?$
- pattern: ^context\.WithTimeout(# use context\.WithTimeoutCause instead)?$
- pattern: ^ctx\.Err(# use context\.Cause instead)?$
- pattern: ^fmt\.Errorf(# use errors\.Errorf instead)?$
- pattern: ^platforms\.DefaultString(# use platforms\.Format(platforms\.DefaultSpec()) instead\.)?$
gosec:
excludes:
- G204
- G402
- G115
config:
G306: "0644"
testifylint:
disable:
- "empty"
- "bool-compare"
- "len"
- "negative-positive"
exclusions:
generated: lax
presets:
- comments
- common-false-positives
- legacy
- std-error-handling
rules: rules:
main: -
deny: linters:
- pkg: "github.com/containerd/containerd/platforms" - revive
desc: The containerd platforms package was migrated to a separate module. Use github.com/containerd/platforms instead. text: stutters
- pkg: "io/ioutil" -
desc: The io/ioutil package has been deprecated. linters:
forbidigo: - revive
forbid: text: empty-block
- '^fmt\.Errorf(# use errors\.Errorf instead)?$' -
- '^platforms\.DefaultString(# use platforms\.Format(platforms\.DefaultSpec()) instead\.)?$' linters:
gosec: - revive
excludes: text: superfluous-else
- G204 # Audit use of command execution -
- G402 # TLS MinVersion too low linters:
- G115 # integer overflow conversion - revive
config: text: unused-parameter
G306: "0644" -
testifylint: linters:
disable: - revive
# disable rules that reduce the test condition text: redefines-builtin-id
- "empty" -
- "bool-compare" linters:
- "len" - revive
- "negative-positive" text: if-return
paths:
- .*\.pb\.go$
formatters:
enable:
- gofmt
- goimports
exclusions:
generated: lax
paths:
- .*\.pb\.go$
issues: issues:
exclude-files:
- ".*\\.pb\\.go$"
exclude-rules:
- linters:
- revive
text: "stutters"
- linters:
- revive
text: "empty-block"
- linters:
- revive
text: "superfluous-else"
- linters:
- revive
text: "unused-parameter"
- linters:
- revive
text: "redefines-builtin-id"
- linters:
- revive
text: "if-return"
# show all
max-issues-per-linter: 0 max-issues-per-linter: 0
max-same-issues: 0 max-same-issues: 0

View File

@@ -79,7 +79,7 @@ func (s *ServeCmd) Run(ctx *Context) error {
case "block": case "block":
defer profile.Start(profile.BlockProfile, profilePath).Stop() defer profile.Start(profile.BlockProfile, profilePath).Stop()
default: default:
log.Fatal().Msgf("Unknown profiler: %s", s.Profiler) log.Fatal().Msgf("Unknown profiler: %s", s.Profiler) //nolint:gocritic // defer not set if profiler is unknown
} }
} }

View File

@@ -16,6 +16,10 @@ variable "GOLANGCI_LINT_MULTIPLATFORM" {
default = null default = null
} }
variable "GOLANGCI_FROM_SOURCE" {
default = null
}
target "_common" { target "_common" {
args = { args = {
GO_VERSION = GO_VERSION GO_VERSION = GO_VERSION
@@ -134,6 +138,9 @@ target "lint" {
inherits = ["_common"] inherits = ["_common"]
dockerfile = "./hack/lint.Dockerfile" dockerfile = "./hack/lint.Dockerfile"
target = "lint" target = "lint"
args = {
GOLANGCI_FROM_SOURCE = GOLANGCI_FROM_SOURCE
}
output = ["type=cacheonly"] output = ["type=cacheonly"]
platforms = GOLANGCI_LINT_MULTIPLATFORM != null ? [ platforms = GOLANGCI_LINT_MULTIPLATFORM != null ? [
"darwin/amd64", "darwin/amd64",

View File

@@ -3,20 +3,34 @@
ARG GO_VERSION="1.23" ARG GO_VERSION="1.23"
ARG XX_VERSION="1.6.1" ARG XX_VERSION="1.6.1"
ARG ALPINE_VERSION="3.21" ARG ALPINE_VERSION="3.21"
ARG GOLANGCI_LINT_VERSION="v1.62" ARG GOLANGCI_LINT_VERSION="v2.1.6"
ARG GOLANGCI_FROM_SOURCE="true"
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS base FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS base
ENV GOFLAGS="-buildvcs=false" ENV GOFLAGS="-buildvcs=false"
RUN apk add --no-cache gcc linux-headers musl-dev RUN apk add --no-cache gcc linux-headers musl-dev
COPY --from=xx --link / / COPY --from=xx --link / /
WORKDIR /src WORKDIR /src
FROM base AS golangci-build
ARG GOLANGCI_LINT_VERSION
ADD "https://github.com/golangci/golangci-lint.git#${GOLANGCI_LINT_VERSION}" .
RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/ go mod download
RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/ mkdir -p out && go build -o /out/golangci-lint ./cmd/golangci-lint
FROM --platform=$BUILDPLATFORM golangci/golangci-lint:${GOLANGCI_LINT_VERSION}-alpine AS golangci-lint FROM --platform=$BUILDPLATFORM golangci/golangci-lint:${GOLANGCI_LINT_VERSION}-alpine AS golangci-lint
FROM scratch AS golangci-binary-false
COPY --from=golangci-lint /usr/bin/golangci-lint golangci-lint
FROM scratch AS golangci-binary-true
COPY --from=golangci-build /out/golangci-lint golangci-lint
FROM golangci-binary-${GOLANGCI_FROM_SOURCE} AS golangci-binary
FROM base AS lint FROM base AS lint
ARG TARGETPLATFORM ARG TARGETPLATFORM
RUN --mount=type=bind,target=. \ RUN --mount=type=bind,target=. \
--mount=type=cache,target=/root/.cache,id=lint-cache-$TARGETPLATFORM \ --mount=type=cache,target=/root/.cache,id=lint-cache-$TARGETPLATFORM \
--mount=from=golangci-lint,source=/usr/bin/golangci-lint,target=/usr/bin/golangci-lint \ --mount=from=golangci-binary,source=/golangci-lint,target=/usr/bin/golangci-lint \
xx-go --wrap && \ xx-go --wrap && \
golangci-lint run ./... golangci-lint run ./...

View File

@@ -87,11 +87,12 @@ func (c *Client) Send(entry model.NotifEntry) error {
q := u.Query() q := u.Query()
u.RawQuery = q.Encode() u.RawQuery = q.Encode()
hc := http.Client{} cancelCtx, cancel := context.WithCancelCause(context.Background())
ctx, cancel := context.WithTimeout(context.Background(), *c.cfg.Timeout) timeoutCtx, _ := context.WithTimeoutCause(cancelCtx, *c.cfg.Timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent
defer cancel() defer func() { cancel(errors.WithStack(context.Canceled)) }()
req, err := http.NewRequestWithContext(ctx, "POST", u.String(), dataBuf) hc := http.Client{}
req, err := http.NewRequestWithContext(timeoutCtx, "POST", u.String(), dataBuf)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -128,11 +128,12 @@ func (c *Client) Send(entry model.NotifEntry) error {
return err return err
} }
hc := http.Client{} cancelCtx, cancel := context.WithCancelCause(context.Background())
ctx, cancel := context.WithTimeout(context.Background(), *c.cfg.Timeout) timeoutCtx, _ := context.WithTimeoutCause(cancelCtx, *c.cfg.Timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent
defer cancel() defer func() { cancel(errors.WithStack(context.Canceled)) }()
req, err := http.NewRequestWithContext(ctx, "POST", u.String(), dataBuf) hc := http.Client{}
req, err := http.NewRequestWithContext(timeoutCtx, "POST", u.String(), dataBuf)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -89,11 +89,12 @@ func (c *Client) Send(entry model.NotifEntry) error {
q.Set("token", token) q.Set("token", token)
u.RawQuery = q.Encode() u.RawQuery = q.Encode()
hc := http.Client{} cancelCtx, cancel := context.WithCancelCause(context.Background())
ctx, cancel := context.WithTimeout(context.Background(), *c.cfg.Timeout) timeoutCtx, _ := context.WithTimeoutCause(cancelCtx, *c.cfg.Timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent
defer cancel() defer func() { cancel(errors.WithStack(context.Canceled)) }()
req, err := http.NewRequestWithContext(ctx, "POST", u.String(), bytes.NewBuffer(jsonBody)) hc := http.Client{}
req, err := http.NewRequestWithContext(timeoutCtx, "POST", u.String(), bytes.NewBuffer(jsonBody))
if err != nil { if err != nil {
return err return err
} }

View File

@@ -81,11 +81,12 @@ func (c *Client) Send(entry model.NotifEntry) error {
q := u.Query() q := u.Query()
u.RawQuery = q.Encode() u.RawQuery = q.Encode()
hc := http.Client{} cancelCtx, cancel := context.WithCancelCause(context.Background())
ctx, cancel := context.WithTimeout(context.Background(), *c.cfg.Timeout) timeoutCtx, _ := context.WithTimeoutCause(cancelCtx, *c.cfg.Timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent
defer cancel() defer func() { cancel(errors.WithStack(context.Canceled)) }()
req, err := http.NewRequestWithContext(ctx, "POST", u.String(), dataBuf) hc := http.Client{}
req, err := http.NewRequestWithContext(timeoutCtx, "POST", u.String(), dataBuf)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -122,11 +122,12 @@ func (c *Client) Send(entry model.NotifEntry) error {
} }
u.Path = path.Join(u.Path, "api/v1/chat.postMessage") u.Path = path.Join(u.Path, "api/v1/chat.postMessage")
hc := http.Client{} cancelCtx, cancel := context.WithCancelCause(context.Background())
ctx, cancel := context.WithTimeout(context.Background(), *c.cfg.Timeout) timeoutCtx, _ := context.WithTimeoutCause(cancelCtx, *c.cfg.Timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent
defer cancel() defer func() { cancel(errors.WithStack(context.Canceled)) }()
req, err := http.NewRequestWithContext(ctx, "POST", u.String(), dataBuf) hc := http.Client{}
req, err := http.NewRequestWithContext(timeoutCtx, "POST", u.String(), dataBuf)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -9,6 +9,7 @@ import (
"github.com/crazy-max/diun/v4/internal/model" "github.com/crazy-max/diun/v4/internal/model"
"github.com/crazy-max/diun/v4/internal/msg" "github.com/crazy-max/diun/v4/internal/msg"
"github.com/crazy-max/diun/v4/internal/notif/notifier" "github.com/crazy-max/diun/v4/internal/notif/notifier"
"github.com/pkg/errors"
) )
// Client represents an active signalrest notification object // Client represents an active signalrest notification object
@@ -62,11 +63,12 @@ func (c *Client) Send(entry model.NotifEntry) error {
return err return err
} }
hc := http.Client{} cancelCtx, cancel := context.WithCancelCause(context.Background())
ctx, cancel := context.WithTimeout(context.Background(), *c.cfg.Timeout) timeoutCtx, _ := context.WithTimeoutCause(cancelCtx, *c.cfg.Timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent
defer cancel() defer func() { cancel(errors.WithStack(context.Canceled)) }()
req, err := http.NewRequestWithContext(ctx, "POST", c.cfg.Endpoint, bytes.NewBuffer(body)) hc := http.Client{}
req, err := http.NewRequestWithContext(timeoutCtx, "POST", c.cfg.Endpoint, bytes.NewBuffer(body))
if err != nil { if err != nil {
return err return err
} }

View File

@@ -110,11 +110,12 @@ func (c *Client) Send(entry model.NotifEntry) error {
return err return err
} }
hc := http.Client{} cancelCtx, cancel := context.WithCancelCause(context.Background())
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(10)*time.Second) timeoutCtx, _ := context.WithTimeoutCause(cancelCtx, 10*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent
defer cancel() defer func() { cancel(errors.WithStack(context.Canceled)) }()
req, err := http.NewRequestWithContext(ctx, "POST", webhookURL, bytes.NewBuffer(jsonBody)) hc := http.Client{}
req, err := http.NewRequestWithContext(timeoutCtx, "POST", webhookURL, bytes.NewBuffer(jsonBody))
if err != nil { if err != nil {
return err return err
} }

View File

@@ -8,6 +8,7 @@ import (
"github.com/crazy-max/diun/v4/internal/model" "github.com/crazy-max/diun/v4/internal/model"
"github.com/crazy-max/diun/v4/internal/msg" "github.com/crazy-max/diun/v4/internal/msg"
"github.com/crazy-max/diun/v4/internal/notif/notifier" "github.com/crazy-max/diun/v4/internal/notif/notifier"
"github.com/pkg/errors"
) )
// Client represents an active webhook notification object // Client represents an active webhook notification object
@@ -47,11 +48,12 @@ func (c *Client) Send(entry model.NotifEntry) error {
return err return err
} }
hc := http.Client{} cancelCtx, cancel := context.WithCancelCause(context.Background())
ctx, cancel := context.WithTimeout(context.Background(), *c.cfg.Timeout) timeoutCtx, _ := context.WithTimeoutCause(cancelCtx, *c.cfg.Timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent
defer cancel() defer func() { cancel(errors.WithStack(context.Canceled)) }()
req, err := http.NewRequestWithContext(ctx, "POST", c.cfg.Endpoint, bytes.NewBuffer(body)) hc := http.Client{}
req, err := http.NewRequestWithContext(timeoutCtx, "POST", c.cfg.Endpoint, bytes.NewBuffer(body))
if err != nil { if err != nil {
return err return err
} }

View File

@@ -68,7 +68,7 @@ func newInClusterClient(opts Options) (*kubernetes.Clientset, error) {
config.Host = opts.Endpoint config.Host = opts.Endpoint
} }
if opts.TLSInsecure != nil { if opts.TLSInsecure != nil {
config.TLSClientConfig.Insecure = *opts.TLSInsecure config.Insecure = *opts.TLSInsecure
} }
return kubernetes.NewForConfig(config) return kubernetes.NewForConfig(config)
@@ -80,7 +80,7 @@ func newExternalClusterClientFromFile(opts Options, file string) (*kubernetes.Cl
return nil, err return nil, err
} }
if opts.TLSInsecure != nil { if opts.TLSInsecure != nil {
configFromFlags.TLSClientConfig.Insecure = *opts.TLSInsecure configFromFlags.Insecure = *opts.TLSInsecure
} }
return kubernetes.NewForConfig(configFromFlags) return kubernetes.NewForConfig(configFromFlags)
@@ -113,7 +113,7 @@ func newExternalClusterClient(opts Options) (*kubernetes.Clientset, error) {
} }
} }
if opts.TLSInsecure != nil { if opts.TLSInsecure != nil {
config.TLSClientConfig.Insecure = *opts.TLSInsecure config.Insecure = *opts.TLSInsecure
} }
return kubernetes.NewForConfig(config) return kubernetes.NewForConfig(config)

View File

@@ -5,6 +5,7 @@ import (
"time" "time"
"github.com/containers/image/v5/types" "github.com/containers/image/v5/types"
"github.com/pkg/errors"
) )
// Client represents an active docker registry object // Client represents an active docker registry object
@@ -43,9 +44,11 @@ func New(opts Options) (*Client, error) {
func (c *Client) timeoutContext() (context.Context, context.CancelFunc) { func (c *Client) timeoutContext() (context.Context, context.CancelFunc) {
ctx := context.Background() ctx := context.Background()
var cancel context.CancelFunc = func() {} var cancelFunc context.CancelFunc = func() {}
if c.opts.Timeout > 0 { if c.opts.Timeout > 0 {
ctx, cancel = context.WithTimeout(ctx, c.opts.Timeout) cancelCtx, cancel := context.WithCancelCause(ctx)
ctx, _ = context.WithTimeoutCause(cancelCtx, c.opts.Timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent
cancelFunc = func() { cancel(errors.WithStack(context.Canceled)) }
} }
return ctx, cancel return ctx, cancelFunc
} }