- Scope: Governs the entire repository. If another
AGENTS.mdexists deeper, it overrides in its subtree. - Cursor rules: none in
.cursor/rules/or.cursorrules. - Copilot rules: none in
.github/copilot-instructions.md. - Purpose: Give human and agent contributors a concise, reliable playbook.
- Language: Go modules (root +
client/submodule). - Go version: CI uses 1.25 (install >=1.25).
- Main binaries:
pd-server,pd-ctl,pd-recover, tool suite.
- Default all:
make build(pd-server, pd-ctl, pd-recover). - Full dev loop:
make dev(build + check + tools + test). - Lightweight:
make dev-basic(build + check + basic-test). - No dashboard:
make pd-server-basic(setsSWAGGER=0 DASHBOARD=0). - With swagger spec:
SWAGGER=1 make build(runsswagger-spec). - With custom dashboard distro: set
DASHBOARD_DISTRIBUTION_DIRthenmake build. - Specific tool:
make pd-ctl,make pd-tso-bench, etc. - Race build:
WITH_RACE=1 make build(CGO on,-race). - FIPS/boringcrypto:
ENABLE_FIPS=1 make build. - Simulator:
make simulator. - Docker image:
make docker-image(needs Docker daemon).
- Default pipeline: from
client/, runmake(static + tidy + test). - Tests with race/tags:
make test(deadlock tag, race, cover; auto failpoints). - Fast tests:
make basic-test. - CI coverage:
make ci-test-job. - Lint/static:
make static(gofmt, golangci-lint, leakcheck).
- Primary entry:
make check(tidy + static + generate-errdoc). - Static combo:
make staticruns gofmt -s, golangci-lint, leakcheck (PACKAGE_DIRECTORIES/SUBMODULES respected). - Tidy:
make tidymust leavego.mod/go.sumclean (CI enforces empty diff). - Error docs:
make generate-errdoc(updateserrors.toml). - golangci-lint config: see
.golangci.yml(gofmt/goimports/gci formatters; depguard bansgithub.com/pkg/errors,go.uber.org/atomic,math/rand; prefersmath/rand/v2; goheader copyright; revive + testifylint extensive; waitgroup-by-value forbidden). - leakcheck excludes
tests/server/join/join_test.go. - Formatter order (gci): standard, default,
prefix(github.com/pingcap),prefix(github.com/tikv/pd), blank.
- Full suite:
make test(tags deadlock, CGO=1, race, cover; auto failpoints). - Basic fast:
make basic-test(no tests/ packages, no race; failpoints enabled). - UT binary:
make ut->./bin/pd-ut run --ignore tests --race --junitfile ./junitfile. - CI shard:
make ci-test-job JOB_INDEX=N(needs dashboard-ui + pd-ut built). - TSO function:
make test-tso-function(tagswithout_dashboard,deadlock, race on). - Real cluster:
make test-real-cluster(usestests/integrations/realcluster; wipes~/.tiup/data/pd_real_cluster_test). - Coverage split:
make test-with-cover-parallelaftermake split. - Clean test artifacts:
make clean-test(clears/tmp/pd_tests*, go test cache, UT bins, playground log).
- Keep failpoints enabled only for tests; disable immediately after (
make failpoint-disableormake clean-test) to avoid polluting the codebase. - Prefer make targets that auto-enable/disable failpoints; if running
go testmanually, bracket with enable/disable. - Never commit generated failpoint files or leave failpoints enabled; verify
git statusis clean before pushing. - If failpoint-related tests misbehave, rerun after
make failpoint-disable && make failpoint-enableto ensure a clean state.
- Use gci/goimports ordering: stdlib | third-party | pingcap | tikv/pd | blank.
- Avoid dot-imports; revive rule will warn.
- Keep imports deduped; run gofmt/goimports/gci.
- gofmt rewrite rule:
interface{}->any(seemake fmt). - Run
make fmtor gofmt on touched files; respect project ordering.
- Prefer concrete types; keep structs zero-value friendly; init maps/slices before use.
- Pointers for large structs; avoid pointer-to-interface and copying mutex holders.
- Typed constants with iota for enums; keep error codes in
errors.toml(regenerate viamake generate-errdoc). - First param
context.Contextfor external effects; never store contexts in structs. - Acronyms uppercase (TSO, API, HTTP); package dirs lower_snake; filenames kebab/underscore ok.
- Exported identifiers need GoDoc starting with the name; avoid stutter (
pd.PDServer->Server).
- Wrap with
github.com/pingcap/errors(errors.Wrap/Annotate) orfmt.Errorf("...: %w", err). - No ignored errors unless allowed in
.golangci.ymlerrcheck exclusions. - Error strings: lowercase, no trailing punctuation.
- Prefer sentinel errors over panic; panic only on programmer bugs/impossible states.
- HTTP handlers: use errcode +
errorResp; avoidhttp.Error.
- Use existing structured logging (zap/log); avoid
fmt.Println. - Include useful fields (component, store id, region id); never log secrets/PII.
- Cancel timers/tickers; close resources with defer and error checks.
sync.WaitGroupmust be a pointer (revive rule).- Prevent goroutine leaks: pair with cancellation; consider errgroup.
- Guard shared state with mutex/RWMutex; keep lock ordering consistent.
- Do not capture loop vars by pointer; copy inside loop (
v := val). - Range-in-closure/address rules enforced; make local copies.
- Preallocate slices/maps when size known.
- Swagger:
make swagger-spec(SWAGGER=1) regenerates; keep annotations current. - Easyjson:
make generate-easyjsonupdatespkg/response/region.go. - JSON tags explicit; use
omitemptywhere sensible. - Update docs when API/build/test flows change.
- Prometheus-style metrics; name with subsystem + unit; avoid high-cardinality labels.
metrics/package has helpers; add tests for new metrics when feasible.
- Mind allocations; reuse buffers/pools where appropriate.
- Avoid per-request reflection; keep hot paths lean.
- Use context-aware timeouts and backoff for retries.
- Never commit secrets/keys/tokens.
- Use
crypto/randfor security needs; avoid insecure randomness. - Do not disable lint/security checks without discussion.
- Tools live in
.tools/bin;make install-toolsinstalls pinned versions (golangci-lint v2.6.0, etc.). tools.gopins tool deps; avoid adding runtime deps without justification; runmake tidyafter changes and ensure clean diff.
- Assets embedded via
scripts/embed-dashboard-ui.sh; run throughmake dashboard-uidependency. - Skip dashboard for speed with
DASHBOARD=0ormake pd-server-basic. - Custom distro info: set
DASHBOARD_DISTRIBUTION_DIRthenmake dashboard-replace-distro-info.
- Run
make tidyafter dep changes;go.mod/go.summust stay clean. - Run
make fmt/gofmt; ensure gci/goimports ordering. - Clean with
make clean(removes failpoints, tmp tests, bin,.tools/bin). - Avoid committing generated artifacts (junitfile, coverage, dashboard caches) unless required.
- Follow
.github/pull_request_template.md; includeIssue Number: close|ref #...line. - Commit subject:
pkg: message, <=70 chars; blank line; body wrapped 80 chars; addSigned-off-byviagit commit -s. - Multi-area: separate packages with commas; use
*:for broad changes.
NEXT_GEN=1builds/tests usenextgentag and disable dashboard; ensure compatibility.- Resource group/keyspace features live under
server/resource dirs—follow existing patterns.
- Return errors up-stack; use
errors.Is/Asfor sentinel checks. - Ensure cleanups on all exits; prefer named cleanups with defer.
- gRPC services use interceptors; add auth/validation in handlers, not transport.
- HTTP handlers validate payloads and return proper status codes; avoid panics.
- Mirror patterns in existing tests for expected behavior.
- Use
git blame/git logto follow conventions; avoid history rewrites.
- Read this file; look for deeper
AGENTS.mdbefore editing. - Before PR: run
make checkand the narrowest relevantgo test(with tags). At minimum runmake basic-testfor touched packages. - Keep imports ordered, gofmt clean, modules tidy.
- Respect depguard bans, revive/testifylint findings; fix before submission.
- Ensure
PD_EDITIONset correctly; enable failpoints where required. - Keep error handling consistent with
pingcap/errorsand errcode usage. - Avoid new global state; keep concurrency safe; close resources.
- Leave workspace clean (no stray tmp, coverage, or generated dashboard files).