Skip to main content

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

  1. Create infrahub_sync/adapters/<name>.py following existing adapter patterns
  2. Add connection configuration schema and an example under examples/
  3. Provide a diff pathway before enabling sync
  4. Document required environment variables and expected error cases
  5. Create a documentation page in docs/docs/adapters/
  6. Add the adapter to the sidebar in docs/sidebars.ts

Invoke tasks

View all available tasks:

uv run invoke --list

Common tasks:

TaskDescription
linter.format-ruffFormat Python code with ruff
linter.lint-ruffLint Python code with ruff
linter.lint-pylintLint Python code with pylint
linter.lint-yamlLint YAML files with yamllint
linter.lint-tyType-check with ty
docs.format-rumdlFormat Markdown and MDX with rumdl
docs.rumdlLint Markdown and MDX with rumdl
docs.generateGenerate CLI documentation
docs.docusaurusBuild documentation website
formatRun rumdl formatting, then Ruff formatting and safe fixes
lintRun rumdl, Ruff, Pylint, yamllint, and ty in order