name: Test on: push: branches: - master pull_request: types: - opened - synchronize schedule: # cron every week on monday - cron: "0 0 * * 1" env: UV_NO_SYNC: true jobs: test: strategy: matrix: os: [ windows-latest, macos-latest ] python-version: [ "3.14" ] include: - os: ubuntu-latest python-version: "3.9" coverage: coverage - os: macos-latest python-version: "3.10" coverage: coverage - os: windows-latest python-version: "3.12" coverage: coverage - os: ubuntu-latest python-version: "3.13" coverage: coverage # Ubuntu with 3.13 needs coverage for CodSpeed benchmarks - os: ubuntu-latest python-version: "3.13" coverage: coverage codspeed: codspeed - os: ubuntu-latest python-version: "3.14" coverage: coverage fail-fast: false runs-on: ${{ matrix.os }} env: UV_PYTHON: ${{ matrix.python-version }} steps: - name: Dump GitHub context env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - uses: actions/checkout@v6 - name: Set up Python uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} - name: Setup uv uses: astral-sh/setup-uv@v7 with: enable-cache: true cache-dependency-glob: | pyproject.toml uv.lock - name: Install Dependencies run: uv sync --locked --no-dev --group tests --extra all - run: mkdir coverage - name: Test if: matrix.codspeed != 'codspeed' run: uv run bash scripts/test.sh env: COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }} CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }} - name: CodSpeed benchmarks if: matrix.codspeed == 'codspeed' uses: CodSpeedHQ/action@v4 env: COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }} CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }} with: mode: simulation run: uv run coverage run -m pytest tests/ --codspeed # Do not store coverage for all possible combinations to avoid file size max errors in Smokeshow - name: Store coverage files if: matrix.coverage == 'coverage' uses: actions/upload-artifact@v5 with: name: coverage-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('**/coverage/.coverage.*') }} path: coverage include-hidden-files: true coverage-combine: needs: [test] runs-on: ubuntu-latest steps: - name: Dump GitHub context env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - uses: actions/checkout@v6 - uses: actions/setup-python@v6 with: python-version-file: ".python-version" - name: Setup uv uses: astral-sh/setup-uv@v7 with: enable-cache: true cache-dependency-glob: | pyproject.toml uv.lock - name: Install Dependencies run: uv sync --locked --no-dev --group tests --extra all - name: Get coverage files uses: actions/download-artifact@v6 with: pattern: coverage-* path: coverage merge-multiple: true - run: ls -la coverage - run: uv run coverage combine coverage - run: uv run coverage html --title "Coverage for ${{ github.sha }}" - name: Store coverage HTML uses: actions/upload-artifact@v5 with: name: coverage-html path: htmlcov include-hidden-files: true - run: uv run coverage report --fail-under=100 # https://github.com/marketplace/actions/alls-green#why check: # This job does nothing and is only used for the branch protection if: always() needs: - coverage-combine runs-on: ubuntu-latest steps: - name: Dump GitHub context env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - name: Decide whether the needed jobs succeeded or failed uses: re-actors/alls-green@release/v1 with: jobs: ${{ toJSON(needs) }}