What a Well-Kept Repository Ships
A checklist for what a well-maintained repository should ship, in its documentation, its code, and its automation.
How to use it: not every repo needs every item. Items marked (A) are advanced, worth it for OSS projects, monorepos, or anything with external contributors. Everything unmarked is the baseline.
Sections marked conditional only apply when the repo is that kind of project (an HTTP service, a containerized app, a Kubernetes workload).
Index #
- 1. Documentation
- 2. Code
- 3. Testing
- 4. API artifacts (conditional: HTTP/gRPC services)
- 5. Build and runtime (conditional: containerized apps)
- 6. CI/CD
- 7. Repository metadata
- Minimum viable set
1. Documentation #
1.1 README.md #
- Project overview: what it does and, more importantly, why it exists
- Status badges: CI build, test coverage, latest release, stability level
- Stability / maturity level (
development→alpha→beta→stable→deprecated) - Support policy: who maintains it, where to ask, expected response time
- Installation instructions
- Running the app locally
- Configuring your environment (
.env.examplecommitted,.envgit-ignored) - Usage examples (copy-pasteable, actually tested)
- Architecture diagram or a short “how it fits together” section
- Link to contribution guidelines
- License information
- A README per module/subpackage, not only at the root (A)
- Autogenerated status sections, delimited by markers, so they never drift (A)
1.2 Governance and policy files #
LICENSE(+NOTICEif you redistribute third-party code)CONTRIBUTING.md: local setup, how to run tests, PR title/description rules, review expectationsCODEOWNERS: ownership per directory, drives automatic review requestsSECURITY.md: how to report a vulnerability, privatelyCODE_OF_CONDUCT.mdAGENTS.md/CLAUDE.md: AI-assisted contribution policy (disclosure trailer, what agents may and may not do).github/pull_request_template.md.github/ISSUE_TEMPLATE/: bug report, feature request, plusconfig.ymlpointing to support channels- Issue triage policy: labels, priorities, stale policy (A)
- Maintainer/approver roles and how to become one (A)
1.3 Deeper docs (docs/) #
- Release process, written down and repeatable
- Testing guide: how to run each test tier locally
- Onboarding guide for new modules/components (A)
- ADRs (Architecture Decision Records): the why behind the design
- Runbook / operational docs: alerts, dashboards, common failures
- Generated reference docs: every config option, default, and emitted metric, produced from the source of truth rather than hand-written (A)
1.4 Changelog and releases #
CHANGELOG.mdfollowing SemVer / Keep a Changelog- Changelog fragments: one small file per PR, assembled at release time. Kills merge conflicts and forces the author to state user impact (A)
- Separate changelog for API/breaking changes vs. user-facing changes (A)
- Tagged releases with release notes generated from the changelog
- Documented versioning and deprecation policy
2. Code #
2.1 Layout and conventions #
- Consistent, documented project layout
- License/SPDX header on every source file, enforced by the linter
- Package-level doc comment on each package (
doc.goor equivalent) - Linter config committed, with an explicit linter set and justified per-path exceptions, not the tool’s defaults
- Formatter enforced in CI, not left to the reviewer
- Import restrictions enforced (no forbidden/internal imports leaking out) (A)
- A task runner (Makefile / justfile / npm scripts) with standard targets:
test,lint,fmt,build,run,integration-test,tidy - The same commands work at the root and inside each module (A)
2.2 Configuration #
- Typed config struct with an explicit
Validate()and clear error messages - Fail fast on invalid config at startup, never mid-request
- Committed example config, loaded by a real test
- Published config schema (JSON Schema / equivalent) for editor autocomplete and CI validation (A)
examples/with complete, scenario-based configurations: not snippets- Secrets never in config files or in the repo; injected at runtime
- Structured logging, metrics, and tracing wired in and documented
2.3 Single source of truth / generated code (A) #
- Declarative metadata file per component (owners, stability, config, emitted telemetry)
- Code, docs, and README sections generated from it
- CI verifies the generated output is up to date: drift becomes a failing build instead of stale documentation
3. Testing #
3.1 Unit tests #
- Unit tests that actually assert behavior, not just execute lines
- Table-driven tests for branchy logic
- Deterministic: no sleeps, no real clock, no network
- Test fixtures (
testdata/) versioned, with a command to regenerate them
3.2 Integration and end-to-end #
- Integration tests isolated behind a build tag / separate command so they don’t slow the unit run
- Real dependencies via ephemeral containers (Testcontainers or equivalent)
- End-to-end tests against a realistic deployment (A)
- Contract tests for consumed and provided APIs (A)
3.3 Performance and robustness (A) #
- Benchmarks for hot paths, with a documented way to compare runs
- Load tests with a stated performance baseline
- Fuzz tests for anything that parses external input
- Leak detection: goroutines, connections, file descriptors
- Race detector enabled in CI
3.4 Coverage #
- Coverage report generated in CI and published
- Coverage threshold committed to the repo, split into project and patch targets (e.g. 85% overall, 95% on the diff)
- Per-module/per-component coverage, so a large repo doesn’t hide a bad corner behind a good average (A)
4. API artifacts (conditional: HTTP/gRPC services) #
- OpenAPI / Swagger spec, versioned in the repo
- Spec generated from or validated against the code, so it can’t drift
- Postman / Insomnia / Bruno collection
.httprequest files (runnable from the editor)curl.txtwith copy-pasteable examples- Documented authentication flow
- Error catalogue: codes, meanings, and how to recover
- Documented versioning and deprecation path for endpoints
5. Build and runtime (conditional: containerized apps) #
5.1 Docker #
Dockerfilewith multi-stage build- Minimal, pinned base image (distroless/slim), non-root user
.dockerignore- Healthcheck defined
- Reproducible builds: pinned dependencies, no
latest - Image vulnerability scan in CI (A)
- SBOM generated and published with the image (A)
5.2 Docker Compose #
docker-compose.ymlthat brings the whole stack up with one command- Environment-specific overrides (
docker-compose.dev.yml,.prod.yml) - Dependencies (DB, broker, cache) included so a new dev needs nothing else
5.3 Kubernetes (conditional) #
- Manifests, or a Helm chart with a documented
values.yaml - Resource requests and limits set
- Liveness / readiness / startup probes
- Secrets management (External Secrets, SOPS, sealed-secrets, never plain)
- Ingress configuration
- Per-environment overlays (Kustomize) or value files
NetworkPolicy,PodDisruptionBudget, security context (A)- Manifests linted and validated in CI (
kubeconform,helm lint) (A)
6. CI/CD #
6.1 Basic checks #
- Lint
- Format check
- Unit tests
- Coverage report + threshold enforcement
- Build the artifact (binary and/or image)
- Integration tests, in a separate job
- Required status checks configured on the protected branch
- Build matrix across supported OS/versions (A)
- Scope detection: only run what the diff actually affects (A)
- Job sharding to keep wall-clock time sane on large repos (A)
6.2 Security #
- Dependency vulnerability scanning
- SAST (CodeQL or equivalent)
- Secret scanning enabled
- License compliance check on dependencies
- Workflow files themselves linted (
actionlint,zizmor) (A) - Shell scripts linted (
shellcheck) (A) - Minimal
permissions:per workflow; third-party actions pinned to a SHA - OpenSSF Scorecard (A)
6.3 Dependencies #
- Automated updates (Renovate / Dependabot) with a grouping strategy
- Lockfile committed
- Automated tidy/prune check so the manifest can’t drift
- Public API compatibility check between versions (A)
6.4 Repository automation (A) #
- Auto-assign reviewers from
CODEOWNERS - Auto-label PRs and issues by affected area
- Ping owners on new issues touching their area
- Stale issue/PR handling
- First-time contributor welcome
- Merge freeze during a release window
- Periodic repo health report (open issues, unowned areas)
- Release preparation automated (version bump, changelog assembly, tag)
7. Repository metadata #
- Topics/tags with the technologies used, for discoverability
- Clear, one-line repository description
- Branch protection rules on the default branch
- Signed commits or signed tags (A)
- Archive/deprecation notice when a repo stops being maintained
Minimum viable set #
If you only do ten things, do these:
- README that gets someone running locally in under five minutes
LICENSECONTRIBUTING.md.env.examplecommitted, secrets out of the repo- Unit tests with a coverage threshold enforced in CI
- Lint + format enforced in CI
- Multi-stage
Dockerfileand a one-commanddocker-compose up CHANGELOG.mdand tagged releases- Dependency and vulnerability scanning
- Branch protection with required checks