Thanks for helping. pgbot is a read-only PostgreSQL diagnostics CLI; a few invariants are load-bearing, so please read the short list below before a PR.
go build ./cmd/pgbot # static binary (CGO stays off)
go test ./... # unit tests; DB-dependent ones self-skip
scripts/gate.sh # the real gate — builds HEAD, not your working treescripts/gate.sh refuses a dirty tree, then builds and tests the committed HEAD
in an isolated clone across four arches. Run it before pushing — a green
working-tree go test can hide a partial commit that doesn't compile.
Integration tests run against a real database when PGBOT_TEST_DSN (a superuser
DSN unlocks the doc-verify guard via PGBOT_TEST_SUPERUSER_DSN) is set:
docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=pw postgres:18 -c shared_preload_libraries=pg_stat_statements
PGBOT_TEST_SUPERUSER_DSN=postgres://postgres:pw@127.0.0.1:5432/postgres go test ./internal/collect/ -run IntegrationCI also runs gofmt -l, go vet, go test -race, golangci-lint, and
govulncheck; keep them green.
- Read-only, always. pgbot pins
default_transaction_read_only, a 15sstatement_timeout, and a 2slock_timeout, and runs everything insideBEGIN READ ONLY. It never writes to the target. - Never execute an inspected query. Only plain
EXPLAINis allowed —EXPLAIN ANALYZE(or theANALYZEoption in any form) is banned tree-wide and a CI grep enforces it. New raw-SQL surfaces must reusesanitizeQuery+ the READ ONLY transaction. - Findings are deterministic. Every finding is computed in Go from a
model.Context(internal/findings). The LLM layer explains findings; it never generates them. - No PII in a
model.Context.pg_stat_activitytext goes throughconn.ScrubQueryText; connection strings throughconn.RedactConnString;pg_stat_statementstext is scrubbed too (it stores utility statements verbatim). --jsonis additive. Add fields withomitempty, or bumpmodel.SchemaVersionand regenerate the schema (go run ./tools/schemagen).- Every finding has a docs page. A new finding needs a catalog entry
(
internal/findings/catalog.go) and adocs/findings/<id>.md; a CI test enforces the pairing and that the page's verify query actually runs.
See docs/release.md — tag → GoReleaser → per-channel smoke jobs, and which secret each distribution channel (npm, Homebrew) needs.
Conventional-commit prefixes (feat:, fix:, docs:, test:, chore:, ci:)
keep the changelog readable. Keep changes focused; commit each logical unit.