Skip to content

chore(lint): adopt golangci-lint formatters and importas - #925

Merged
gaborage merged 4 commits into
mainfrom
chore/golangci-formatters-and-importas
Aug 8, 2026
Merged

chore(lint): adopt golangci-lint formatters and importas#925
gaborage merged 4 commits into
mainfrom
chore/golangci-formatters-and-importas

Conversation

@gaborage

@gaborage gaborage commented Aug 8, 2026

Copy link
Copy Markdown
Owner

What

Adopts the golangci-lint v2 formatters: layer (gofumpt, gci) for the uber-go guide's
"Group Similar Declarations" and "Import Grouping and Aliasing" sections, plus a
conflict-only importas map (11 alias inconsistencies across 5 packages) and revive's
deep-exit ("Exit in Main", 0 findings). The reformat lands in the same commit because
golangci-lint run enforces formatters as issues.

Impact

None for consumers. make fmt now runs golangci-lint fmt instead of go fmt — required,
since go fmt cannot fix gofumpt/gci findings and make check would reformat then fail
lint anyway. It also reaches 5 //go:build integration files that run never loads.

Verification

The gci section order is standard, default, prefix(go-bricks) deliberately: the naive
standard, default merges third-party back into the go-bricks group across 197 files.
Reformat is idempotent — a second fmt --diff pass returns empty.

Summary by CodeRabbit

  • Chores

    • Standardized project formatting through a consistent, pinned formatter workflow.
    • Enhanced linting rules to improve import aliases, code formatting, and exit handling.
    • Updated contributor guidance and migration tooling to use the standardized formatting command.
  • Refactor

    • Cleaned up import organization, spacing, declarations, aliases, and test formatting across the codebase.
  • Tests

    • Updated test fixtures and formatting without changing test coverage or expected behavior.

Enables the two uber-go style-guide rules the linter set was missing —
"Import Grouping and Aliasing" and the stricter formatting behind "Group
Similar Declarations" — plus revive's "Exit in Main" check, and applies
the resulting reformat in the same commit so CI never sees a red tree.

Formatters are a TOP-LEVEL block in golangci-lint v2; listing gofumpt or
gci under linters.enable is a hard config error ("can't load config:
gofumpt is a formatter"). `golangci-lint run` still reports their output
as ordinary issues ("File is not properly formatted (gci)"), which is why
the reformat has to land here.

gci's section order is the load-bearing decision. Measured against the
pre-adoption tree at v2.12.2:

  standard, default, prefix(go-bricks)      ->  70 files / 290 lines
  standard, default                         -> 138 files / 589 lines
  standard, prefix(go-bricks), default      -> 199 files / 806 lines
    (the last needs custom-order: true; without it gci normalises back
     to the first)

Prefix-last wins because most of the tree already separates third-party
from go-bricks in exactly that order by hand. Dropping the prefix section
is not merely 2x the churn: re-running the no-prefix order against the
formatted tree rewrites 197 files, merging third-party imports back into
the go-bricks block in every one. Do not "simplify" it later. goimports
is deliberately not enabled: it overlaps gci on grouping and the two
fight.

gofumpt runs with extra-rules: false. extra-rules was measured (+24
lines) and rejected — it implements no rule the uber-go guide asks for.

importas is a conflict-only map: five import paths the tree already
aliases two or more ways, each pinned to the majority alias (11 findings,
all fixed here). go.opentelemetry.io/otel/metric/noop is pinned to
metricnoop even though the plurality spelling was metricznoop — that is
a typo, and the two extra findings buy its deletion. net/http is
deliberately absent: 56 unaliased sites against 7 nethttp and 6 stdhttp
is not a convention to ratchet, it is a decision nobody has made yet.
no-unaliased and no-extra-aliases stay off; either turns an 11-site
cleanup into a ~40-file sweep. Already-consistent paths are left out
rather than added as ratchets, because a version-stamped path such as
otel/semconv/v1.NN.0 silently stops matching on the next bump.

cmd/seal-payload is excluded from the go-jose entry: it is the only file
set importing both go-jose/v4 (package name `jose`) and go-bricks/jose,
so one must be aliased away, and the go-bricks package is the dominant
one there. Keeping `gojose` on the vendor import is precisely the
collision-avoidance case uber-go's aliasing guidance prescribes.

revive gains `deep-exit`. It measured 0 findings and was verified to fire
against a planted os.Exit outside main/init, so it is a pure ratchet.
Note revive.rules REPLACES the default set, so the existing re-declared
defaults are untouched.

The Makefile change is not cosmetic. `make check` is `fmt lint ...`, and
`go fmt` cannot fix a gofumpt or gci finding — leaving it would reformat
and then fail lint on every run. Both Makefiles now call `golangci-lint
fmt` at the same pinned version their `lint` target uses. The two
subcommands also cover different file sets: `run` is package-scoped and
never loads the //go:build integration files, while `fmt` walks the tree
and does reach them — 5 needed reformatting.
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 01c02369-6629-466c-99ea-3810598eab53

📥 Commits

Reviewing files that changed from the base of the PR and between eee8527 and 7540f7e.

📒 Files selected for processing (101)
  • .golangci.yml
  • CONTRIBUTING.md
  • Makefile
  • app/app.go
  • app/app_builder_test.go
  • app/app_test.go
  • app/bootstrap_test.go
  • app/debug_health_test.go
  • app/factory_resolver_integration_test.go
  • app/factory_resolver_test.go
  • app/health_test.go
  • app/lifecycle_test.go
  • app/managers_test.go
  • app/module.go
  • app/module_registry_test.go
  • cache/errors_test.go
  • cache/manager_test.go
  • cmd/seal-payload/main.go
  • config/config_test.go
  • config/errors_test.go
  • config/tenant_store_test.go
  • database/errors_integration_test.go
  • database/execute_test.go
  • database/internal/builder/filter.go
  • database/internal/builder/filter_test.go
  • database/internal/builder/join_filter.go
  • database/internal/builder/join_filter_test.go
  • database/internal/builder/query_builder.go
  • database/internal/builder/query_builder_test.go
  • database/internal/columns/parser_test.go
  • database/internal/columns/registry_test.go
  • database/internal/tracking/metrics.go
  • database/oracle/connection.go
  • database/oracle/connection_integration_test.go
  • database/oracle/connection_test.go
  • database/postgresql/connection.go
  • database/postgresql/connection_integration_test.go
  • database/postgresql/connection_test.go
  • database/testing/fake_db_test.go
  • database/testing/null_scan_test.go
  • database/transaction_test.go
  • database/types/subquery_test.go
  • httpclient/client.go
  • httpclient/client_test.go
  • httpclient/logging_test.go
  • httpclient/tls_test.go
  • inbox/config_test.go
  • inbox/coverage_test.go
  • inbox/inbox_test.go
  • inbox/module_test.go
  • inbox/store_integration_test.go
  • inbox/store_oracle_test.go
  • inbox/store_postgres_test.go
  • inbox/testing/mock_inbox_test.go
  • internal/resourcepool/resourcepool_test.go
  • internal/tenantstore/tenantstore_test.go
  • jose/jose_properties_test.go
  • jose/opener_test.go
  • jose/resolver_test.go
  • jose/testing/helpers_test.go
  • keystore/keystore_test.go
  • keystore/module_test.go
  • keystore/testing/assertions.go
  • logger/adapter_test.go
  • logger/logger_test.go
  • messaging/amqp_client.go
  • messaging/amqp_client_test.go
  • messaging/amqp_test.go
  • messaging/otel_test.go
  • messaging/tenant_publisher.go
  • multitenant/cleanup_test.go
  • observability/noop.go
  • observability/provider.go
  • observability/shutdown_test.go
  • outbox/config_test.go
  • outbox/module_test.go
  • outbox/publisher.go
  • outbox/publisher_test.go
  • outbox/store_oracle_test.go
  • outbox/store_postgres_test.go
  • outbox/test_helpers_test.go
  • outbox/testing/mock_outbox_test.go
  • scheduler/api_handlers_test.go
  • scheduler/cidr_middleware_test.go
  • scheduler/job_test.go
  • scheduler/module.go
  • scheduler/module_test.go
  • scheduler/test_helpers_test.go
  • server/handler.go
  • server/jose.go
  • server/jose_options_test.go
  • server/logger_test.go
  • server/request_enrich.go
  • server/server_test.go
  • server/timeout_test.go
  • server/trace_context.go
  • testing/mocks/query_builder.go
  • tools/migration/Makefile
  • tools/migration/internal/commands/builders_test.go
  • tools/migration/internal/commands/quiesce_test.go
  • trace/trace_test.go
💤 Files with no reviewable changes (5)
  • app/app.go
  • config/tenant_store_test.go
  • messaging/tenant_publisher.go
  • database/oracle/connection_test.go
  • httpclient/logging_test.go

Walkthrough

The pull request standardizes Go linting and formatting. It updates repository commands and contributor guidance, then applies import ordering, alias naming, spacing, declaration grouping, signature formatting, and explicit octal syntax across source and test files.

Changes

Lint and formatting standardization

Layer / File(s) Summary
Lint policy configuration
.golangci.yml
Enables importas and deep-exit, adds known alias rules and exclusions, and configures gci and gofumpt.
Formatter workflow
Makefile, tools/migration/Makefile, CONTRIBUTING.md
Replaces go fmt ./... guidance and targets with the pinned golangci-lint fmt command.
Source and test normalization
app/..., cache/..., config/..., database/..., httpclient/..., inbox/..., jose/..., keystore/..., logger/..., messaging/..., observability/..., outbox/..., scheduler/..., server/..., testing/..., trace/...
Applies the configured import ordering and aliases, reformats declarations and test tables, adds spacing, and changes file permission literals to explicit octal syntax. Runtime behavior remains unchanged.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Poem

A rabbit checks imports in a neat little row,
While formatters make every Go file glow.
Aliases hop, and blank lines align,
No runtime changes cross the finish line.
“Run make fmt!” the rabbit cheers,
With tidy code for many ears.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main changes: adopting golangci-lint formatters and the importas linter.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/golangci-formatters-and-importas

Comment @coderabbitai help to get the list of available commands.

gaborage and others added 3 commits August 7, 2026 19:48
The Makefile's new `fmt` comment claimed `golangci-lint run` is
package-scoped and never loads //go:build integration files, so only
`fmt` reaches them. Measured against this tree at v2.12.2 that is false:
planting a gci violation and then a gofumpt violation in
app/debug_integration_test.go, `golangci-lint run ./app/...` reports both
("File is not properly formatted"). The formatters see build-excluded
files under either subcommand. The practical consequence inverts the
original note — `run` (and therefore CI) fails on integration-file
formatting drift that only `fmt` can repair — so the comment now says
that instead.

CONTRIBUTING.md still told contributors `make fmt` formats with `go fmt`,
which this branch replaced with `golangci-lint fmt`.

No config or Go-source change: the .golangci.yml formatters/importas/revive
blocks and the ~100-file reformat are unchanged.
The `fmt` target's rationale claimed the formatters see //go:build integration
files "under both subcommands", and concluded that `golangci-lint run` would
fail on drift only `fmt` can repair. The opposite holds. Measured at the pinned
v2.12.2 with one planted gofumpt violation (a blank line after a func's opening
brace) in inbox/store_integration_test.go:

  golangci-lint fmt --diff <file>  -> reports the diff, exit 1
  golangci-lint run ./inbox/...    -> 0 issues, exit 0

`run` is untagged here and in CI — ci-v2.yml has three lint jobs
(lint-framework, lint-migrate-tool, lint-docs) and none passes
-tags=integration — so it never loads those files at all. `fmt` is therefore
the only thing keeping the five integration files formatted, which is a reason
to keep this target, not evidence that `run` backstops it.

The target itself is unchanged and its main justification still holds: `run`
does report gofumpt/gci findings as ordinary issues on untagged files, so
`go fmt` cannot sit here without leaving `make check` to fail its own lint step.
@sonarqubecloud

sonarqubecloud Bot commented Aug 8, 2026

Copy link
Copy Markdown

@gaborage
gaborage merged commit 80096ca into main Aug 8, 2026
28 checks passed
@gaborage
gaborage deleted the chore/golangci-formatters-and-importas branch August 8, 2026 02:27
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