Contributing¶
Thanks for wanting to contribute. Here's how we work.
PR Process¶
- Pick or create an issue — check the issue tracker first
- Branch off
develop— the default working branch;mainis the release branch — use the naming convention below - Make your changes — follow the coding standards
- Write/update tests — PRs without tests for new features will be asked to add them
- Open a pull request — fill out the template
- Address review feedback — iterate until approved
- Merge — squash merge into
develop
What CI Checks¶
Every PR runs .github/workflows/ci.yml. It must be green, and several gates are ratchets — the tracked number may only improve:
| Gate | What passes |
|---|---|
ruff format --check . | Zero formatting diffs |
ruff check . | Violation count ≤ ruff-baseline.txt (shrink the baseline when you fix violations) |
scripts/run_mypy.sh \| mypy-baseline filter | No mypy errors beyond mypy-baseline.txt |
| Unit tests + coverage | Total line coverage ≥ coverage-baseline.txt; changed lines ≥ 60% (diff-cover vs origin/develop) |
| OpenAPI contract | Committed openapi.json matches the live spec; untyped-response count ≤ openapi-untyped-baseline.txt |
| Alembic migrations | alembic upgrade head reaches head on a fresh DB, is idempotent, and survives seeded data through downgrade/re-upgrade |
| Compose validation | docker compose config passes for base + prod + dev file combinations |
| Security scan | Bandit + pip-audit (advisory) |
See Coding Standards for how to run the lint/type gates locally and when to update the baseline files.
Branch Naming¶
Text Only
feature/short-description # New feature
fix/issue-or-bug-description # Bug fix
chore/task-description # Maintenance, deps, CI
docs/what-changed # Documentation only
refactor/what-changed # Code restructuring
Examples:
feature/mailbox-export-apifix/dkim-key-rotation-crashchore/upgrade-mysql-exporterdocs/add-scaling-guide
Commit Conventions¶
We use conventional commits. The format:
Types:
| Type | When to use |
|---|---|
feat | New feature |
fix | Bug fix |
docs | Documentation only |
refactor | Code change that doesn't fix a bug or add a feature |
test | Adding or updating tests |
chore | Build, CI, dependency updates |
perf | Performance improvement |
Examples:
Text Only
feat: add mailbox export endpoint
fix: prevent DKIM crash when key file is missing
docs: add SendGrid migration guide
refactor: extract email validation into shared module
test: add integration tests for webhook delivery
chore: update Postfix base image to 3.8
Keep the first line under 72 characters. If you need more detail, add a blank line and then a longer description.
Code Review¶
Every PR needs at least one approval before merging. Here's what reviewers look for:
- Does it work? — Does the feature actually do what it claims?
- Tests — Are there tests? Do they cover the important cases?
- Error handling — What happens when things fail?
- Security — Any new inputs validated? Secrets exposed? SQL injection?
- Performance — Will this cause issues at scale? N+1 queries? Missing indexes?
- Docs — If user-facing, are the docs updated?
- Style — Does it follow our coding standards?
Responding to Feedback¶
- Don't take it personally — reviews are about the code, not you
- Address every comment — either fix it or explain why you disagree
- Push new commits — don't force-push during review (it breaks comment threads)
What Makes a Good PR¶
- Small and focused — one feature or fix per PR
- Good description — explain what changed and why
- Self-reviewed — look at your own diff before requesting review
- No unrelated changes — don't refactor something unrelated in the same PR
- Tests pass — CI must be green
PR Template¶
Markdown
## What
Brief description of the change.
## Why
What problem does this solve? Link to issue if applicable.
## How
How does this work? Any design decisions worth noting?
## Testing
How did you test this? What should reviewers check?
## Checklist
- [ ] Tests added/updated
- [ ] Docs updated (if user-facing)
- [ ] No secrets committed
- [ ] Migration included (if DB changes)
- [ ] Baseline files updated if a ratchet count dropped
Development Setup¶
See Getting Started for the full dev environment setup.
Questions?¶
Open an issue or ask in the team channel. There are no stupid questions — email infrastructure is genuinely complex, and nobody knows all of it.