Skip to content

Contributing

Kaveh Razavi edited this page Oct 15, 2026 · 3 revisions

9.9. Contributing

This is the short path from a fresh clone to a merged first change. Set up, run one safe test for the area you touch, and open a pull request against the right branch. Adding or changing a service has its own walkthrough in Adding a service. Report security findings through the security policy, never as a public issue.

1. Before you start

  • Pick or open an issue on the project's GitHub issue tracker. For anything larger than a typo, say on the issue what you plan to change, so the scope is agreed before you write it.
  • You need git, uv, and Python 3.10 or newer for the bootstrapper. Backend tests run under Python 3.12, which uv can download for you. The documentation checks in §3.3 also need make and the native Cairo library that diagram rendering links. Install libcairo2 on Debian and Ubuntu, or run brew install cairo on macOS. Docker is only needed to run the stack itself and the Docker-backed suites described in §4.

2. Set up

git clone https://github.com/thekaveh/atlas.git
cd atlas
git switch develop
uv sync --project bootstrapper

uv sync installs the bootstrapper and its development group (pytest and the documentation build) into bootstrapper/.venv. Every command below runs from the repository root.

3. Run one safe test for your change

Run the test closest to what you changed before you push. Each command below runs without Docker, without a running stack, and without any live service endpoint. The first run downloads what it needs, so it needs network access once. That is Python 3.12 and the Backend's packages for §3.2, and fonts and diagram assets for the documentation build.

You change Run
The bootstrapper: start.sh/stop.sh flow, wizard, manifest loader or validator, docs tooling §3.1, choosing the test file named after the module you touched
A service manifest (services/<name>/service.yml) §3.1 and §3.3, then the checks in Adding a service
The Backend API (services/backend/app/app/) §3.2
Documentation only §3.3

3.1. Bootstrapper

uv run --project bootstrapper pytest bootstrapper/tests/test_manifests.py -q

Swap in the test file for the module you changed, or narrow with -k <name>. The whole suite is uv run --project bootstrapper pytest bootstrapper/tests -q, but it takes around 40 minutes and part of it needs Docker (see §4).

3.2. Backend

The Backend has its own dependencies. This block creates a throwaway Python 3.12 environment with the runtime and test requirements. It uses the same tested constraint as CI, runs one non-live test file, and removes the environment afterwards. Paste it as one block. The parentheses keep the cd and the cleanup inside a subshell. set -e stops at the first failing step, so a failed download reports itself instead of a missing interpreter.

(
  set -e
  cd services/backend/app/app
  BACKEND_TEST_ROOT="$(mktemp -d)"
  trap 'rm -rf "$BACKEND_TEST_ROOT"' EXIT
  BACKEND_TEST_VENV="$BACKEND_TEST_ROOT/venv"
  uv venv --python 3.12 "$BACKEND_TEST_VENV"
  VIRTUAL_ENV="$BACKEND_TEST_VENV" uv pip install \
    -r requirements.txt -r requirements-dev.txt -c requirements-test-locked.txt
  env -u ATLAS_TEST_REDIS_URL -u ATLAS_COMFYUI_LIVE_ENDPOINT \
    -u ATLAS_TEI_RERANKER_LIVE_ENDPOINT \
    "$BACKEND_TEST_VENV/bin/python" -m pytest tests/test_readiness.py -q -W error
)

Replace tests/test_readiness.py with the test file for the route or service you changed, or use tests/ for the whole non-live suite.

requirements-test-locked.txt must pin every package it shares with requirements-locked.txt at the same version, so the tests run the versions the image ships. scripts/check_test_locks.py fails when the two differ.

3.3. Documentation

make docs-check
uv run --project bootstrapper python scripts/check_doc_links.py
PYTHONPATH=bootstrapper uv run --project bootstrapper python -m bootstrapper.docs.regen --all --check

Documentation is published to three surfaces (this repository, the documentation site and the wiki) from the same Markdown. make docs-check builds all three and fails on drift. Per-service READMEs carry generated blocks: regenerate them with regen --all instead of editing them by hand.

4. What needs Docker, and what is live

  • Docker-backed suites. The backup, restore and database-role suites drive real containers, and the Compose checks (test_fragment_equivalence.py, test_source_permutations.py) call docker compose. Without Docker they skip or cannot run. The required CI jobs run all of them, so you only need them locally when you change those areas.
  • Live smokes. A few Backend tests talk to a real Redis, ComfyUI or reranker, and skip unless their ATLAS_* endpoint variable is set. The command in §3.2 unsets those variables, so it never reaches a live service.
  • The stack. ./start.sh needs Docker and is not needed to run any test above.

5. Branch, pull request and required checks

  • Branch from develop, for example git switch -c fix/1234-readiness-timeout origin/develop.

  • Open the pull request against develop. Never target main: it only receives release pull requests that promote develop (see Releasing).

  • Title it as a Conventional Commits subject: type: summary. Add an optional (scope) after the type, and a ! before the colon only for a breaking change. Examples: fix(backend): report Redis as unavailable when the readiness probe times out, docs(contributing): link the backend test path. Releasing §6 lists the accepted types.

    Title edits rerun the full workflow. A single-commit pull request can default to its commit subject under the current squash policy. Before merging, ensure the final squash subject matches the checked title; the changelog generator reads that subject.

  • Four required checks must pass, all run by .github/workflows/services-lint.yml:

    • Manifest lint + unit tests
    • Compose merge + byte-equivalence + source-permutation matrix
    • Docs drift + audit scripts
    • Build-validation (Dockerfile + requirements.txt installability)

    Adding a service §13.4 says what each one catches and lists a representative local subset. The first is a gate over four parallel jobs. A failing unit test shows up first as a red Bootstrapper suite without Docker (fast) check. A new commit or edit cancels the pull request's previous run.

  • Before merge, the branch must be up to date with develop (merge develop into it) and every review conversation must be resolved. A maintainer squash-merges it.

  • Link the issue in the pull request body. The pull request targets develop, not the default branch, so GitHub does not close the issue on merge. A maintainer closes it once the change lands.

6. What reviewers look for

  • One concern per pull request, with a body that says what changed, why, and which commands you ran with their result.
  • A test for every behaviour change, in the existing test file for that module where one exists.
  • Documentation updated wherever the changed behaviour is described.
  • A new or moved image pin or model source comes with its row in the supply-chain license inventory. make docs-check fails until the row matches the pin.
  • Generated files regenerated, not edited: .env.example (uv run --project bootstrapper python -m services.env_assembler) and the per-service Dependencies & Integrations blocks (regen). Never edit kong-dynamic.yml; every start rebuilds it.
  • Adding a tracked file moves the complexity ratchet. bootstrapper/tests/test_maintenance_baseline.py then asks for a higher tracked_files in .maintenance.json and in its EXPECTED_BASELINE_SNAPSHOT. Add a refresh note that names the new file.
  • No secret, API key or token-shaped literal anywhere in the diff, tests included.
  • Docker images, base configurations and scanner exceptions stay as they are unless the issue is about them.

7. Where to go next

Atlas Documentation

Clone this wiki locally