.golangci.yml
Ref: Size: 5.7 KiB History
# golangci-lint v2 configuration for Eitri.
#
# Two tiers (see docs/architecture.md and the CI workflow):
# - correctness + boundary linters: BLOCK merge (run via `make lint`)
# - complexity/style linters: WARN only at first, promoted to block
# one at a time as the baseline stays clean
#
# depguard here is the fast, in-editor half of the boundary enforcement; the
# transitive-closure half lives in internal/arch/arch_test.go (R1–R6).
version: "2"
run:
timeout: 5m
linters:
default: none
# BLOCK TIER — these are clean today and `make lint` fails CI on any finding.
# The complexity/style WARN tier (errcheck, revive, gocyclo, funlen, gocritic,
# misspell, unconvert, nakedret) is run informationally by `make lint-extra`
# (exit code 0). Their settings live below so they apply when enabled via CLI.
# Promote a warn linter into this list once its baseline is clean.
enable:
# --- correctness ---
- govet
- staticcheck # also covers the old gosimple + stylecheck
- ineffassign
- unused
- bodyclose # http bodies in cloudhv.socketClient / imagecache (prod only)
- rowserrcheck # database/sql in server/store
- sqlclosecheck # *sql.Rows in store.scanVM / ListVMs
# --- context discipline (matches the ctx-first-arg convention) ---
- contextcheck
- containedctx # forbid context.Context stored in structs; Engine takes ctx per-call
# --- decoupling / boundaries ---
- depguard # encodes R1/R2/R4 as import bans (below)
- ireturn # nudge toward concrete returns; allow at the documented seams
settings:
staticcheck:
# Quietly drop the purely-stylistic quickfix nags (redundant type in decl,
# embedded-field selector) — keep the correctness checks blocking.
checks:
- all
- -QF1008
- -QF1011
gocyclo:
min-complexity: 20 # reconcile.create is the one legit outlier; excluded below
funlen:
lines: 90
statements: 60
ireturn:
allow:
- error
- empty
- stdlib
# ssh.Signer is the idiomatic return across the x/crypto/ssh API (keys and
# CAs ARE signers); returning the concrete key type would be worse. A
# documented seam, per this tier's policy.
- golang.org/x/crypto/ssh.Signer
# ssh.PublicKey is likewise the idiomatic x/crypto/ssh type for a fetched
# CA / host key; the concrete key types are unexported. Same seam.
- golang.org/x/crypto/ssh.PublicKey
depguard:
rules:
# R1 cross-plane bans apply to production code only; integration tests
# (e.g. agent/syncclient/client_test.go) legitimately wire up both planes.
# The transitive-closure check in internal/arch also covers production only.
server-no-agent: # R1: control plane must not import data plane
files:
- "**/internal/server/**"
- "!**/*_test.go"
deny:
- pkg: github.com/a73x/eitri/internal/agent
desc: control plane (server) must not import data plane (agent)
server-no-exec: # R2: the server is a control plane and never shells out
files:
- "**/internal/server/**"
deny:
- pkg: os/exec
desc: the server expresses desired state and must never shell out
agent-no-server: # R1: data plane must not import control plane
files:
- "**/internal/agent/**"
- "!**/*_test.go"
deny:
- pkg: github.com/a73x/eitri/internal/server
desc: data plane (agent) must not import control plane (server)
no-protojson: # R15: protobuf names are not a contract
files:
- "$all"
deny:
- pkg: google.golang.org/protobuf/encoding/protojson
desc: protobuf serialises field numbers, not names; renaming a wire message must stay free — serialise through internal/server/api/types
domain-no-transport: # R4: pure domain stays serialization-agnostic
files:
- "**/internal/agent/state/**"
- "**/internal/agent/seed/**"
- "**/internal/agent/ipalloc/**"
- "**/internal/server/registry/**"
deny:
- pkg: net/http
desc: domain logic must not depend on the HTTP stack
- pkg: github.com/quic-go/quic-go
desc: domain logic must not depend on QUIC
- pkg: github.com/a73x/eitri/internal/transport
desc: domain logic must not depend on the transport layer
exclusions:
# Auto-exclude files carrying a "DO NOT EDIT" generated header (the .pb.go).
generated: lax
rules:
# reconcile.create is an intentionally linear, well-commented state
# machine: every step is a create side effect with its own failure path.
- path: internal/agent/reconcile/reconcile.go
linters:
- funlen
- gocyclo
source: "func \\(e \\*Engine\\) create"
# Generated protobuf — belt-and-suspenders alongside `generated: lax`.
- path: 'internal/pb/.*\.pb\.go'
linters:
- govet
- gocritic
- revive
- unused
- funlen
- gocyclo
- staticcheck
# Tests: fakes and table tests run long; ctx-in-struct is fine in fixtures;
# an unclosed httptest response body in a test leaks nothing meaningful.
- path: _test\.go
linters:
- funlen
- containedctx
- bodyclose
# contextcheck adds value in the core libraries; the CLI entrypoints use
# context.Background in shutdown paths by design.
- path: (^|/)cmd/
linters:
- contextcheck