Contributing
Read Architecture first — it shows where parser, guard, enrich and blocklist sit in the data flow. For package signatures, see API / Packages.
Setup
git clone https://github.com/lenny-ts/caddy-analyzer.git && cd caddy-analyzer
go version # 1.25+
Test & lint — exact commands (as in CI)
# full suite (what CI runs)
go vet ./...
go test -race -v ./...
go test -race -coverprofile=coverage.out ./... && go tool cover -func=coverage.out | tail
# coverage gate is 55% (CI enforces <55 → error)
# fmt
gofmt -l .
# should be empty; fix with:
gofmt -w .
# lint (golangci-lint v2, 17 linters, see .golangci.yml)
golangci-lint run
# security / vuln
govulncheck ./...
gosec -exclude G204,G302,G304,G401,G501,G505 ./...
# gitleaks (secrets)
gitleaks detect --source .
Test only the module you touched
Faster feedback — run the package, not the whole suite:
go test -race ./pkg/analysis -run TestDetector -count=1
go test -race ./pkg/guard -run TestGuard -count=1
go test -race ./pkg/enrich -count=1
go test -race ./pkg/blocklist -count=1
go test -race ./cmd -run TestResolveSources -count=1
Or a single file (when editing one file):
go test -race ./pkg/parser -run TestParse -count=1 -v
Where to add things
| What | Where | Note |
|---|---|---|
| New detection category | pkg/analysis/detect.go | Add pattern + MITRE ID, add test in detect_test.go, ensure TestPatternUniqueness passes |
| Blocklist feed | pkg/blocklist/blocklist.go + test | Implement Source fetch/parse, respect cacheTTL 7d |
| Firewall backend | pkg/guard/firewall/ | Implement Backend interface, cover Detect() |
| CLI flag | cmd/root.go + cmd/tuning.go | Persistent vs root-only, handle applyTuning |
| Output format | pkg/output/* | Table/JSON/CSV/HTML — keep defang and csvSafe |
Commit convention
Single line, imperative, 35–62 chars. No body, no type: prefix, no version prefix.
Add GeoIP filter for ASN
Fix guard state persistence across restarts
Update blocklist cache TTL handling
Bad: feat: add ... or v0.6.1: fix or multi-line body. See AGENTS.md. Release is via v* tag → GoReleaser + Syft + cosign (you handle merge + tag + push).
PR checklist
go vet ./... && go test -race ./... && golangci-lint rungreen- Tests for new code, docs updated via
node tools/build-docs.js && bash tools/minify.shif you toucheddocs/src/ - Commit message 35–62 chars, imperative