Contributing
This guide covers how to set up a development environment for infrahub-sync and contribute to the project. For the release runbook, see RELEASING.md at the repository root — that's maintainer-only.
Prerequisites
- Python 3.11–3.13 for the full development profile (3.12 recommended). Python 3.10 runs everything except the Sync service.
- uv for dependency management
- Git
Setting up your development environment
Clone the repository
git clone https://github.com/opsmill/infrahub-sync.git
cd infrahub-sync
Install uv
If you don't have uv installed, you can install it with:
curl -LsSf https://astral.sh/uv/install.sh | sh
Or see the uv installation guide for other options.
Install dependencies
uv sync --extra dev --extra prefect --extra service
The prefect and service extras are not optional for development. Without them the type
checker cannot resolve the imports in infrahub_sync/orchestration/ and
infrahub_sync/service/, and the tests that cover them skip themselves.
On Python 3.10 the Sync service is unavailable, so install the direct Prefect profile instead and exclude the service from type checking:
uv sync --python 3.10 --extra dev --extra prefect
Verify your setup
uv run infrahub-sync --help
uv run infrahub-sync configs --help
Development workflow
Before committing any changes, run the following commands in order:
# Run `rumdl fmt .`, then Ruff formatting and safe fixes.
uv run invoke format
# Run `rumdl check .`, then Ruff, Pylint, yamllint, and ty; stop at the first failure.
uv run invoke lint
invoke lint stops after the first gate that fails. Pylint does not pass on a clean
checkout: its leg compares the run against a recorded baseline and fails only on a new
diagnostic code or a count above the recorded maximum.
Validate the CLI
After making changes, verify the CLI still works:
uv run infrahub-sync --help
uv run infrahub-sync configs --help
uv run infrahub-sync runs plan --help
Running tests
The offline gate is what a change has to keep green. It deselects the tests that need a running stack or an external service:
uv run pytest -m "not preview and not integration" -q
Running the full stack locally
To run the Sync HTTP API, its Prefect worker, and a disposable Infrahub against your checkout, see the local development stack.
The suite that exercises that stack is opt-in under the preview marker, and it skips
rather than fails when the stack is not running:
uv run invoke preview.up # start the stack
uv run invoke preview.smoke # seed, then run `pytest -m preview tests/preview`
uv run invoke preview.down --volumes
Code standards
Python style
- Python 3.10–3.13 compatible
- Type hints on new or changed code
- Ruff-formatted and lint-clean
- Clean under
ty; do not add[[tool.ty.overrides]]blocks to mask an error - Public functions and classes require documentation strings
- Raise specific exceptions; avoid broad
except Exception:
Line length
- Maximum line length: 120 characters (configured in
pyproject.toml)
Documentation
If you make user-facing changes (CLI flags, configuration options, new adapters), update the documentation.
Generate command-line documentation
uv run invoke docs.generate
Build documentation site
First-time setup (requires Node.js):
cd docs && pnpm install --frozen-lockfile
Build the site:
uv run invoke docs.docusaurus
Lint markdown files
Markdown structure is checked with rumdl, configured in
pyproject.toml:
uv run invoke docs.format-rumdl # run `rumdl fmt .`
uv run invoke docs.rumdl # run `rumdl check .`
Prose style is checked with Vale, configured in .vale.ini. Run it on
the files you changed:
vale docs/docs/contributing.mdx
Adding a new adapter
- Create
infrahub_sync/adapters/<name>.pyfollowing existing adapter patterns - Add connection configuration schema and an example under
examples/ - Provide a
diffpathway before enablingsync - Document required environment variables and expected error cases
- Create a documentation page in
docs/docs/adapters/ - Add the adapter to the sidebar in
docs/sidebars.ts
Invoke tasks
View all available tasks:
uv run invoke --list
Common tasks:
| Task | Description |
|---|---|
linter.format-ruff | Format Python code with ruff |
linter.lint-ruff | Lint Python code with ruff |
linter.lint-pylint | Lint Python code with pylint |
linter.lint-yaml | Lint YAML files with yamllint |
linter.lint-ty | Type-check with ty |
docs.format-rumdl | Format Markdown and MDX with rumdl |
docs.rumdl | Lint Markdown and MDX with rumdl |
docs.generate | Generate CLI documentation |
docs.docusaurus | Build documentation website |
format | Run rumdl formatting, then Ruff formatting and safe fixes |
lint | Run rumdl, Ruff, Pylint, yamllint, and ty in order |