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.10–3.13 (3.12 recommended)
  • 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 --group dev

This installs all runtime and development dependencies defined in pyproject.toml.

Verify your setup

uv run infrahub-sync --help
uv run infrahub-sync list --directory examples/

Install the Git hooks

prek.toml defines the commit hooks: Ruff formatting and lint for Python, rumdl for Markdown and MDX, and checks for whitespace, YAML, TOML, large files, and private keys. Install them with:

uv run --frozen --extra dev prek install --force

Run the same command in an existing checkout. This project used pre-commit before, and uv sync removes that package, so the .git/hooks/pre-commit file it generated stops working and blocks every commit. --force replaces that file. It also overwrites any other script at that path, so copy your own hook elsewhere first if you keep one there.

Development workflow

Before committing any changes, run the following commands in order:

uv run invoke format # Format code with ruff
uv run invoke lint # Lint code with ruff and pylint
uv run mypy infrahub_sync/ --ignore-missing-imports

Validate the CLI

After making changes, verify the CLI still works:

uv run infrahub-sync --help
uv run infrahub-sync list --directory examples/
uv run infrahub-sync generate --name from-netbox --directory examples/

Running tests

uv run pytest -q

Code standards

Python style

  • Python 3.10–3.13 compatible
  • Type hints on new or changed code
  • Ruff-formatted and lint-clean
  • Mypy-checked (do not increase existing error count)
  • 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 && npm install

Build the site:

uv run invoke docs.docusaurus

Lint markdown files

npx markdownlint-cli "docs/docs/**/*.{md,mdx}"
npx markdownlint-cli --fix "docs/docs/**/*.{md,mdx}"

Changelog entries

Release notes are written by contributors rather than generated from pull request titles, so every pull request into main must add a news fragment under changelog/. CI fails the pull request if it does not.

Create one with towncrier, naming it after the issue or pull request number:

uv run --extra dev towncrier create -c "Short description of what changed." 123.fixed.md

The file must be a direct child of changelog/ named <id>.<type>.md, where the type is one of security, removed, deprecated, added, changed, fixed, or housekeeping. Use + as the identifier when the change has no issue number, for example +short-slug.housekeeping.md.

Nested paths and unknown types are ignored by towncrier, so the check rejects them rather than let your entry disappear at release time.

If a change genuinely needs no entry — a dependency bump or a typo fix — a maintainer can label the pull request ci/skip-changelog.

Do not edit CHANGELOG.md or the version in pyproject.toml by hand. Both are generated when a release is prepared; see RELEASING.md.

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 list and diff pathways 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
docs.generateGenerate CLI documentation
docs.docusaurusBuild documentation website
formatAlias for ruff format
lintRun all linters