CONTRIBUTING.md is the guide for people who want to help. It is not
the README (what the project is), but a separate document about the
workflow for working with the code.
A good CONTRIBUTING file saves maintainers hours: instead of explaining things in every Issue, they send a link.
Minimum contents
1. How to run locally
## Local setup
1. `git clone git@github.com:foo/bar.git`
2. `cd bar`
3. `make install` (or `npm install`)
4. `make test` to verify the setup
Requires: Python 3.11+, Docker.
Without this, a newcomer spends an hour figuring out what to do. Test the instructions on a fresh machine every six months; they tend to go stale.
2. Code style
## Code style
- Run `make fmt` before committing - uses `ruff format` and
`prettier`.
- Run `make lint` to catch issues.
- Tests must be in `tests/`, mirror module structure.
One or two commands that automate everything beats a 50-page style guide. See gpg-signing on pre-commit hooks for automation.
3. Commit format
Often a convention such as conventional-commits:
## Commit messages
We use Conventional Commits:
- `feat: add user login`
- `fix: handle null in pagination`
- `docs: update README`
- `refactor: extract helper`
Reference issue: `fix: timeout (#123)`.
Without a stated format, every PR is a different style. With one, you get a consistent history and auto-generated CHANGELOGs.
4. PR process
## Pull Request process
1. Fork the repo, create a branch from `main` (see
[[upstream-vs-origin]]).
2. Make your changes; keep PRs focused on one thing.
3. Run `make test` locally - CI also runs it.
4. Open a PR with description: what changed, why, what was tested.
5. Address review comments; maintainer merges when approved.
A concrete workflow prevents "why squash?" surprises at merge time.
5. How to report a bug or request a feature
This often belongs in Issues documentation, but it can be convenient here as well:
## Reporting bugs
Use the «Bug report» Issue template. Include:
- what you did,
- what you expected,
- what happened,
- your environment (OS, version, ...).
## Feature requests
Open a Discussion before a PR. We may already have plans.
6. Code of Conduct (optional)
Projects with a large community usually have a separate
CODE_OF_CONDUCT.md or a link from CONTRIBUTING. The Contributor
Covenant is common.
What NOT to include
- Do not write "follow the existing style, ask if unsure." That is
unreadable. Provide concrete commands and rules instead.
- Do not duplicate the README. CONTRIBUTING is about the process (how to contribute); the README is about what (what the project is, how to use it).
- Do not let CONTRIBUTING exceed 200 lines. If it grows beyond
that, split into separate documents (
docs/dev-setup.md,docs/release-process.md).
Where to put it
Three locations (GitHub recognizes all of them):
CONTRIBUTING.mdin the root. Obvious; visible immediately on clone..github/CONTRIBUTING.md. Use this if the root is already crowded.docs/CONTRIBUTING.md. If you have a separate docs/ branch.
When someone opens an Issue or PR on GitHub, a "Read CONTRIBUTING guide" link appears in the right column. This only works when the file is in one of the three standard locations.
Pitfalls
- "Pull requests welcome" in the README with an empty CONTRIBUTING file is a promise without instructions. A newcomer starts a PR without understanding the process, does it wrong, gets frustrated. That outcome is worse than "contributions closed."
- CONTRIBUTING contradicts the README. The README says "Docker required"; CONTRIBUTING says "local Python needed." Walk through both every six months and keep them in sync.
- CONTRIBUTING is outdated. It says
make installbut the project has usedpnpm installfor a year. A contributor spends an hour, opens an Issue saying "it doesn't work." The cycle repeats. Update CONTRIBUTING whenever the underlying infrastructure changes.