fix: Harden fresh installs against undeclared dependencies #93
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [main] | |
| # No base-branch filter: stacked PRs (a branch targeting another PR's | |
| # branch) must run checks too. | |
| pull_request: | |
| concurrency: | |
| group: ci-${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| jobs: | |
| lint: | |
| name: Lint | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up uv | |
| uses: astral-sh/setup-uv@v5 | |
| with: | |
| enable-cache: true | |
| - name: Set up Python | |
| run: uv python install 3.12 | |
| - name: Install dependencies | |
| run: uv sync --frozen | |
| - name: ruff check | |
| run: uv run ruff check src tests | |
| - name: ruff format --check | |
| run: uv run ruff format --check src tests | |
| # Fails when `src` imports a package `pyproject.toml` does not declare. | |
| - name: deptry | |
| run: uv run deptry src | |
| typecheck: | |
| name: Typecheck (mypy) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up uv | |
| uses: astral-sh/setup-uv@v5 | |
| with: | |
| enable-cache: true | |
| - name: Set up Python | |
| run: uv python install 3.12 | |
| - name: Install dependencies | |
| run: uv sync --frozen | |
| - name: mypy | |
| run: uv run mypy src | |
| test: | |
| name: Tests (py${{ matrix.python-version }}) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python-version: ['3.11', '3.12', '3.13'] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up uv | |
| uses: astral-sh/setup-uv@v5 | |
| with: | |
| enable-cache: true | |
| - name: Set up Python ${{ matrix.python-version }} | |
| run: uv python install ${{ matrix.python-version }} | |
| - name: Install dependencies | |
| run: uv sync --frozen --python ${{ matrix.python-version }} | |
| - name: pytest | |
| run: >- | |
| uv run --python ${{ matrix.python-version }} | |
| pytest tests/ | |
| --junitxml=report.xml | |
| --import-mode=importlib | |
| - name: Upload test results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-results-py${{ matrix.python-version }} | |
| path: report.xml | |
| retention-days: 7 | |
| # Runs the test suite with every declared dependency at the oldest version | |
| # `pyproject.toml` allows, | |
| # so a minimum that is too old to work fails the PR | |
| # instead of failing a user who installs with it. | |
| test-minimum-versions: | |
| name: Tests (minimum dependency versions) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up uv | |
| uses: astral-sh/setup-uv@v5 | |
| with: | |
| enable-cache: true | |
| - name: Install lowest direct dependency versions | |
| run: | | |
| uv lock --resolution lowest-direct | |
| uv sync --python 3.11 | |
| - name: pytest | |
| run: uv run --no-sync pytest tests/ --import-mode=importlib | |
| # The other jobs install pinned versions from `uv.lock`, | |
| # so they cannot catch a missing or undeclared dependency. | |
| # This job resolves fresh from PyPI on the oldest and newest supported | |
| # Pythons, since a dependency can drop either end first. | |
| install-smoke: | |
| name: Fresh install smoke test (py${{ matrix.python-version }}) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python-version: ['3.11', '3.13'] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up uv | |
| uses: astral-sh/setup-uv@v5 | |
| - name: Build | |
| run: | | |
| rm -rf dist | |
| uv build | |
| - name: Install wheel into a clean venv and run dm | |
| run: | | |
| uv venv --python ${{ matrix.python-version }} /tmp/smoke | |
| uv pip install --python /tmp/smoke/bin/python dist/*.whl | |
| uv pip check --python /tmp/smoke/bin/python | |
| /tmp/smoke/bin/python -c 'import importlib, pkgutil, datamasque_cli; [importlib.import_module(m.name) for m in pkgutil.walk_packages(datamasque_cli.__path__, "datamasque_cli.")]' | |
| /tmp/smoke/bin/dm --help |