Contributing
TruePPM is in its early days and contributions are welcome. The project uses GitLab for issue tracking and merge requests.
Before you start
Section titled “Before you start”Looking for something to work on? Browse issues carrying the
backlog label —
triaged and not yet scheduled. Check that an issue doesn’t already have an
open merge request or an assignee before you pick it up.
For anything beyond a typo or one-line fix, open an issue first describing what you want to change and why. This avoids wasted effort if the change conflicts with the roadmap or the OSS/Enterprise boundary below.
Who reviews, and how fast: the maintainer monitors the issue tracker and merge requests, and responds within a few business days.
Community channel: GitLab issues and merge requests are the project’s only channel today — there is no separate chat or forum yet.
Code of conduct: participation is governed by the Contributor Covenant 2.1. Be respectful — disagreement about technical choices is fine, disrespect toward contributors is not.
Getting set up
Section titled “Getting set up”git clone git@gitlab.com:trueppm/trueppm.gitcd trueppmmake setup # installs git hooks via pre-commitmake doctor # verifies all prerequisitesSee Installation for Docker Compose setup.
Frontend environment variables
Section titled “Frontend environment variables”The web app reads build-time settings from packages/web/.env (gitignored) — copy
packages/web/.env.example and adjust. Vite only exposes variables prefixed with
VITE_, and a change takes effect only after restarting the dev server.
| Variable | Default | Purpose |
|---|---|---|
VITE_API_BASE_URL | unset (dev proxies to localhost:8000) | Deployed API base URL for production builds |
VITE_FEATURE_FLAGS | unset | JSON build-time defaults for runtime feature flags |
VITE_REACT_QUERY_DEVTOOLS | off | Set to true to show the React Query devtools panel in dev builds |
The React Query devtools panel is off by default so it never occupies screen
real estate during normal development. To debug query-cache state, set
VITE_REACT_QUERY_DEVTOOLS=true in packages/web/.env and restart Vite. It is
gated on dev builds, so it is never present in a production bundle regardless of
this value.
Branching
Section titled “Branching”Branch from main with a conventional prefix:
git checkout main && git pull origin maingit checkout -b feat/my-feature # or fix/, docs/, chore/, test/, refactor/Never commit or push directly to main — all changes go through a feature branch and merge request.
Commits
Section titled “Commits”Follow Conventional Commits:
feat(web): add board/kanban viewfix(api): prevent duplicate membership creationdocs(scheduler): add Monte Carlo CLI examplestest(api): add permission tests for task deletionchore(ci): upgrade Node to 22 in CI imageScopes: scheduler, api, web, helm, sync, docs, ci.
Changelog
Section titled “Changelog”Every MR that touches source code must include a changelog fragment in changelog.d/:
# Naming: <slug>.<type>.md# Types: added, changed, fixed, securityecho "Add board/kanban view with drag-and-drop" > changelog.d/kanban-view.added.mdThe CI changelog:check job blocks the pipeline if the fragment is missing. Fragments are assembled automatically at release time — never edit CHANGELOG.md directly.
Exempt: CI config, dependency bumps, test-only changes, docs-only changes.
Testing
Section titled “Testing”make test # runs all packages# Or per-package:cd packages/scheduler && pytestcd packages/api && pytestcd packages/web && npm test- Scheduler: pytest, coverage >= 80%
- API: pytest with testcontainers PostgreSQL, coverage >= 80%
- Web: vitest, coverage >= 75%
The API suite bans real outbound network sockets: a test that reaches the live
network (usually a misdirected mock) fails fast with a SocketConnectBlockedError
instead of hanging on a connect timeout and flaking. Only the configured database
and Redis hosts are allowed. A test that genuinely needs the network must opt out
explicitly with @pytest.mark.enable_socket — keeping the exception visible and
reviewable.
All MRs require a green pipeline before merge.
Run make pre-push before every git push — it mirrors the blocking CI gates (lint, typecheck, migrations-check, schema-check).
Code style
Section titled “Code style”| Package | Formatter | Linter | Type checker |
|---|---|---|---|
| Scheduler | ruff format | ruff check | mypy |
| API | ruff format | ruff check | mypy —strict |
| Web | prettier | eslint | tsc —noEmit |
make lint # runs all lintersmake typecheck # runs all type checkersMerge requests
Section titled “Merge requests”- Push your branch and open an MR targeting
main - Wait for a green pipeline
- Include: description, testing done, screenshots (if UI), issue link
- Don’t merge with a failing pipeline — fix the root cause on the branch
OSS / Enterprise boundary
Section titled “OSS / Enterprise boundary”Before writing code for a new feature, determine if it belongs in the community or enterprise repo:
- Community (this repo): everything a PM or program team needs to run a program (including multi-project programs)
- Enterprise (separate repo): cross-program/portfolio governance, compliance, and org-level policy
The community edition must never import from trueppm_enterprise. Verify with:
grep -r "trueppm_enterprise" packages/# Must return zero results