Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/file-filters.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ development_files: &development_files
- "development/**"
- "tasks/**"

poetry_files: &poetry_files
uv_files: &uv_files
- "pyproject.toml"
- "poetry.lock"
- "uv.lock"

doc_files: &doc_files
- "docs/**"
Expand All @@ -24,7 +24,7 @@ doc_files: &doc_files

python_all: &python_all
- "**/*.py"
- *poetry_files
- *uv_files
- *ci_config
- *coverage_config

Expand Down
93 changes: 45 additions & 48 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
helm: ${{ steps.changes.outputs.helm_all }}
python: ${{ steps.changes.outputs.python_all }}
yaml: ${{ steps.changes.outputs.yaml_all }}
poetry_files: ${{ steps.changes.outputs.poetry_files }}
uv_files: ${{ steps.changes.outputs.uv_files }}
github_workflows: ${{ steps.changes.outputs.github_workflows }}
steps:
- name: "Check out repository code"
Expand Down Expand Up @@ -129,7 +129,7 @@ jobs:
!contains(needs.*.result, 'failure') &&
!contains(needs.*.result, 'cancelled') &&
needs.files-changed.outputs.documentation == 'true'
needs: ["files-changed", "yaml-lint", "python-lint"]
needs: ["prepare-environment", "files-changed", "yaml-lint", "python-lint"]
runs-on: "ubuntu-22.04"
timeout-minutes: 5
steps:
Expand All @@ -145,10 +145,18 @@ jobs:
cache-dependency-path: docs/package-lock.json
- name: "Install dependencies"
run: npm install
- name: "Setup Python environment"
run: "pip install invoke"
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install UV
uses: astral-sh/setup-uv@v4
with:
version: "${{ needs.prepare-environment.outputs.UV_VERSION }}"
- name: Install dependencies
run: uv sync --all-groups --all-extras
- name: "Build docs website"
run: "invoke docs"
run: "uv run invoke docs"

validate-generated-documentation:
if: |
Expand All @@ -168,17 +176,14 @@ jobs:
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: "Setup Python environment"
run: |
pipx install poetry==${{ needs.prepare-environment.outputs.POETRY_VERSION }}
poetry config virtualenvs.create true --local
poetry env use 3.12
- name: "Install dependencies"
run: "poetry install --no-interaction --no-ansi --extras ctl"
- name: "Setup environment"
run: "poetry run pip install invoke"
- name: "Validate generated documentation"
run: "poetry run invoke docs-validate"
- name: Install UV
uses: astral-sh/setup-uv@v4
with:
version: "${{ needs.prepare-environment.outputs.UV_VERSION }}"
- name: Install dependencies
run: uv sync --all-groups --all-extras
- name: Validate generated documentation
run: uv run invoke docs-validate

validate-documentation-style:
if: |
Expand Down Expand Up @@ -232,24 +237,19 @@ jobs:
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: "Setup environment"
run: |
pipx install poetry==${{ needs.prepare-environment.outputs.POETRY_VERSION }} --python python${{ matrix.python-version }}
poetry config virtualenvs.create true --local
pip install invoke codecov
- name: "Install tomli for Python < 3.11"
if: matrix.python-version == '3.9' || matrix.python-version == '3.10'
run: |
pip install tomli
- name: "Install Package"
run: "poetry install --all-extras"
- name: "Mypy Tests"
run: "poetry run mypy --show-error-codes infrahub_sdk/"
- name: "Unit Tests"
run: "poetry run pytest --cov infrahub_sdk tests/unit/"
- name: Install UV
uses: astral-sh/setup-uv@v4
with:
version: "${{ needs.prepare-environment.outputs.UV_VERSION }}"
- name: Install dependencies
run: uv sync --all-groups --all-extras
- name: Mypy Tests
run: uv run mypy --show-error-codes infrahub_sdk/
- name: Unit Tests
run: uv run pytest --cov infrahub_sdk tests/unit/
- name: "Upload coverage to Codecov"
run: |
codecov --flags python-${{ matrix.python-version }}
uv run codecov --flags python-${{ matrix.python-version }}
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

Expand All @@ -259,11 +259,10 @@ jobs:
- name: "Report coverage for pytest-plugin"
if: matrix.python-version == '3.12'
run: |
source $(poetry env info --path)/bin/activate
coverage run --source=infrahub_sdk -m pytest tests/unit/pytest_plugin
coverage report -m
coverage xml
codecov --flags python-filler-${{ matrix.python-version }}
uv run coverage run --source=infrahub_sdk -m pytest tests/unit/pytest_plugin
uv run coverage report -m
uv run coverage xml
uv run codecov --flags python-filler-${{ matrix.python-version }}
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

Expand All @@ -289,19 +288,17 @@ jobs:
run: |
RUNNER_NAME=$(echo "${{ runner.name }}" | grep -o 'ghrunner[0-9]\+' | sed 's/ghrunner\([0-9]\+\)/ghrunner_\1/')
echo "PYTEST_DEBUG_TEMPROOT=/var/lib/github/${RUNNER_NAME}/_temp" >> $GITHUB_ENV
- name: "Setup environment"
run: |
pipx install poetry==${{ needs.prepare-environment.outputs.POETRY_VERSION }}
poetry config virtualenvs.create true --local
pip install invoke codecov
- name: "Install Package"
run: "poetry install --all-extras"
- name: "Integration Tests"
run: |
poetry run pytest --cov infrahub_sdk tests/integration/
- name: Install UV
uses: astral-sh/setup-uv@v4
with:
version: "${{ needs.prepare-environment.outputs.UV_VERSION }}"
- name: Install dependencies
run: uv sync --all-groups --all-extras
- name: Integration Tests
run: uv run pytest --cov infrahub_sdk tests/integration/
- name: "Upload coverage to Codecov"
run: |
codecov --flags integration-tests
uv run codecov --flags integration-tests
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/define-versions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ name: "Define versions"
on:
workflow_call:
outputs:
POETRY_VERSION:
value: "2.1.3"
UV_VERSION:
value: "0.9.8"

jobs:
prepare:
Expand Down
41 changes: 19 additions & 22 deletions .github/workflows/publish-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,39 +41,36 @@ jobs:
with:
python-version: "3.12"

- name: "Install Poetry"
uses: "snok/install-poetry@v1"
- name: Install UV
uses: astral-sh/setup-uv@v4
with:
version: ${{ needs.prepare-environment.outputs.POETRY_VERSION }}
virtualenvs-create: true
virtualenvs-in-project: true
installer-parallel: true
version: ${{ needs.prepare-environment.outputs.UV_VERSION }}

- name: "Check out repository code"
- name: Check out repository code
uses: "actions/checkout@v5"
with:
submodules: true

- name: "Cache poetry venv"
- name: Cache UV dependencies
uses: "actions/cache@v4"
id: "cached-poetry-dependencies"
id: "cached-uv-dependencies"
with:
path: "./python_sdk/.venv"
key: "venv-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }}"
path: ".venv"
key: "venv-${{ runner.os }}-${{ hashFiles('uv.lock') }}"

- name: "Install Dependencies"
run: "poetry install"
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
- name: Install Dependencies
run: uv sync --all-groups --all-extras
if: steps.cached-uv-dependencies.outputs.cache-hit != 'true'

- name: "Add PyPI secret"
run: "poetry config pypi-token.pypi ${{ secrets.PYPI_TOKEN }}"
- name: Add PyPI secret
run: uv config token pypi ${{ secrets.PYPI_TOKEN }}

- name: "Poetry build"
run: "poetry build"
- name: Build package
run: uv build

- name: "show output"
run: "ls -la dist/"
- name: Show output
run: ls -la dist/

- name: "Poetry push PyPI"
- name: Publish to PyPI
if: ${{ inputs.publish }}
run: "poetry publish"
run: uv publish
38 changes: 18 additions & 20 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,28 +30,22 @@ jobs:
with:
python-version: "3.12"

- name: "Install Poetry"
uses: "snok/install-poetry@v1"
- name: Install UV
uses: astral-sh/setup-uv@v4
with:
version: ${{ needs.prepare-environment.outputs.POETRY_VERSION }}
virtualenvs-create: true
virtualenvs-in-project: true
installer-parallel: true
version: "${{ needs.prepare-environment.outputs.UV_VERSION }}"

- name: "Setup Python environment"
run: |
poetry config virtualenvs.create true --local
poetry env use 3.12
- name: "Install dependencies"
run: "poetry install --no-interaction --no-ansi"
- name: Install dependencies
run: uv sync --all-groups --all-extras

- name: "Check prerelease type"
- name: Check prerelease type
id: release
run: |
echo is_prerelease=$(poetry run python -c "from packaging.version import Version; print(int(Version('$(poetry version -s)').is_prerelease))") >> "$GITHUB_OUTPUT"
echo is_devrelease=$(poetry run python -c "from packaging.version import Version; print(int(Version('$(poetry version -s)').is_devrelease))") >> "$GITHUB_OUTPUT"
echo "version=$(poetry version -s)" >> "$GITHUB_OUTPUT"
echo major_minor_version=$(poetry run python -c "from packaging.version import Version; print(f\"{Version('$(poetry version -s)').major}.{Version('$(poetry version -s)').minor}\")") >> "$GITHUB_OUTPUT"
VERSION=$(uv run python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be able to use uv version --short here.

echo is_prerelease=$(uv run python -c "from packaging.version import Version; print(int(Version('$VERSION').is_prerelease))") >> "$GITHUB_OUTPUT"
echo is_devrelease=$(uv run python -c "from packaging.version import Version; print(int(Version('$VERSION').is_devrelease))") >> "$GITHUB_OUTPUT"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo major_minor_version=$(uv run python -c "from packaging.version import Version; v = Version('$VERSION'); print(f'{v.major}.{v.minor}')") >> "$GITHUB_OUTPUT"
echo latest_tag=$(curl -L \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ github.token }}" \
Expand All @@ -60,10 +54,14 @@ jobs:
| jq -r '.tag_name') >> "$GITHUB_OUTPUT"

- name: Check tag version
if: github.event.release.tag_name != format('v{0}', steps.release.outputs.version)
run: |
echo "Tag version does not match python project version"
exit 1
EXPECTED_TAG="v${{ steps.release.outputs.version }}"
if [ "${{ github.event.release.tag_name }}" != "$EXPECTED_TAG" ]; then
echo "Tag version does not match python project version"
echo "Expected: $EXPECTED_TAG"
echo "Got: ${{ github.event.release.tag_name }}"
exit 1
fi

- name: Check prerelease and project version
if: github.event.release.prerelease == true && steps.release.outputs.is_prerelease == 0 && steps.release.outputs.is_devrelease == 0
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ script.py
.vscode/settings.json
.DS_Store
.python-version
.venv/
.venv
.ruff_cache
**/.ruff_cache
**/.idea/**
Expand Down
32 changes: 19 additions & 13 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,39 +8,45 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

```bash
# Install dependencies
poetry install --with dev --all-extras
uv sync --all-groups --all-extras

# Install specific groups
uv sync --group tests # Testing dependencies only
uv sync --group lint # Linting dependencies only
uv sync --extra ctl # CLI dependencies only
uv sync --all-groups --all-extras # All optional dependencies

# Format code
poetry run invoke format
uv run invoke format

# Run linting (ruff + mypy + yamllint + markdownlint)
poetry run invoke lint
uv run invoke lint

# Run unit tests with coverage
poetry run pytest --cov infrahub_sdk tests/unit/
uv run pytest --cov infrahub_sdk tests/unit/

# Run integration tests
poetry run pytest tests/integration/
uv run pytest tests/integration/

# Generate documentation
poetry run invoke docs
uv run invoke docs

# Validate documentation
poetry run invoke docs-validate
uv run invoke docs-validate
```

### Testing Specific Components

```bash
# Run tests for specific modules
poetry run pytest tests/unit/test_client.py
poetry run pytest tests/unit/test_node.py
uv run pytest tests/unit/test_client.py
uv run pytest tests/unit/test_node.py

# Run with verbose output
poetry run pytest -v tests/unit/
uv run pytest -v tests/unit/

# Run with parallel execution
poetry run pytest -n 4 tests/unit/
uv run pytest -n 4 tests/unit/
```

## Architecture Overview
Expand Down Expand Up @@ -148,7 +154,7 @@ CLI commands are auto-documented and organized in `infrahub_sdk/ctl/`.

```bash
# Generate all docs
poetry run invoke docs
uv run invoke docs

# Start development server (requires Node.js)
cd docs && npm start
Expand All @@ -168,7 +174,7 @@ cd docs && npm start

GitHub Actions workflow runs:

1. Multi-version Python testing (3.9-3.13)
1. Multi-version Python testing (3.10-3.13)
2. Comprehensive linting pipeline
3. Documentation generation and validation
4. Integration testing with Infrahub containers
Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,18 @@ Installs infrahub-sdk together with all the extras.
```bash
pip install 'infrahub-sdk[all]'
```

### Development setup with UV

If you're developing the SDK and using UV for dependency management, you can install specific dependency groups:

```bash
# Install development dependencies
uv sync --all-groups --all-extras

# Install specific groups
uv sync --group tests # Testing dependencies only
uv sync --group lint # Linting dependencies only
uv sync --group ctl # CLI dependencies only
uv sync --all-groups --all-extras # All optional dependencies
```
Loading