Skip to content

Gate CI on golangci-lint and govulncheck - #397

Merged
folbricht merged 2 commits into
masterfrom
lint-ci
Aug 30, 2026
Merged

folbricht merged 2 commits into
masterfrom
lint-ci

Conversation

@folbricht

Copy link
Copy Markdown
Owner

Adds a lint gate to CI and fixes what it found.

CI

Two new jobs, both separate from the build matrix so a lint failure and a test failure are reported side by side:

  • golangci-lint — the standard set: errcheck, govet, ineffassign, staticcheck, unused.
  • govulncheck — reports only vulnerabilities the code actually reaches, so a finding is worth acting on rather than triaging away. It runs against the current stable toolchain rather than the go.mod version, since most findings are in the standard library and the fix for those is a Go upgrade.

.golangci.yml turns off two categories, both style rather than defects:

  • staticcheck's QF refactoring suggestions — dropping an embedded type from a selector that names it for clarity, applying De Morgan's law to a condition that reads better as written.
  • errcheck on a deferred Close, which has nowhere to report to. A Close called outright stays flagged, and that is where the real bugs turned out to be.

The default caps on reported issues are lifted; at three per distinct message they hid most of what was there.

The go-vet pre-commit hook is enabled too, since it needs no tooling beyond the toolchain. golangci-lint stays commented out there because it needs the binary on PATH, and CI enforces it either way.

What it found

Most of the 72 findings were an intentional discard that just wasn't written as one. Four were worth changing:

  • LocalStore.StoreChunk renamed the temp file into place without checking that closing it succeeded. A close failure means the chunk was never flushed, so the store would publish a chunk it had not written.
  • The RemoteHTTP, S3 and SFTP index stores closed the pipe write end with a plain Close. A failing WriteTo therefore ended the stream cleanly and the store uploaded a short index as if it were whole. They now close with the error, as the OCI index store already did. Same pattern in tar and mtree.
  • Cache.Close returned only the upstream store's error, discarding the cache store's.
  • FormatDecoder.Next ignored the error from advancing past an unread element, leaving the stream misaligned so the next read reported a bogus header instead of the real failure.

Deprecated calls in tests were replaced: cobra's SetOutput with SetOut/SetErr, minio's Credentials.Get with GetWithContext.

golangci-lint run ./... reports 0 issues, and the suite passes under -race.

Mostly making an intentional discard explicit, but four were worth
changing:

LocalStore.StoreChunk renamed the temp file into place without checking
that closing it succeeded. A close failure means the chunk was never
flushed, so the store would publish a chunk it had not written.

The RemoteHTTP, S3 and SFTP index stores serialize an index into a pipe
from a goroutine and closed the write end with a plain Close. A failing
WriteTo therefore ended the stream cleanly and the store uploaded a
short index as if it were whole. They now close with the error, as the
OCI index store already did. Same pattern in the tar and mtree commands.

Cache.Close returned only the upstream store's error, discarding the
cache store's, and FormatDecoder.Next ignored the error from advancing
past an unread element, leaving the stream misaligned so the next read
reported a bogus header instead of the real failure.

Deprecated calls in tests replaced: cobra's SetOutput with SetOut and
SetErr, minio's Credentials.Get with GetWithContext.
golangci-lint runs the standard set (errcheck, govet, ineffassign,
staticcheck, unused) in its own job so a lint failure and a test failure
are reported side by side.

Two categories are turned off in .golangci.yml, both because they report
style rather than defects: staticcheck's QF refactoring suggestions, and
errcheck on a deferred Close, which has nowhere to report to. A Close
called outright stays flagged, which is where the real bugs turned out
to be. The default caps on reported issues are lifted; at three per
distinct message they hid most of what was there.

govulncheck reports only vulnerabilities the code actually reaches. It
runs against the current stable toolchain rather than the go.mod
version, since most findings are in the standard library and the fix for
those is a Go upgrade.

Also enables the go-vet pre-commit hook, which needs no extra tooling.
@folbricht
folbricht merged commit 005027c into master Aug 30, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

⌂ 换网址