name: Tests

on:
  pull_request:
  push:
    branches:
      - main

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

jobs:
  tests:
    name: ${{ matrix.session }} ${{ matrix.python-version }} / ${{ matrix.os }}
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - { python-version: "3.13", os: ubuntu-latest, session: "pre-commit" }
          - { python-version: "3.13", os: ubuntu-latest, session: "safety" }
          - { python-version: "3.13", os: ubuntu-latest, session: "mypy" }
          - { python-version: "3.12", os: ubuntu-latest, session: "mypy" }
          - { python-version: "3.11", os: ubuntu-latest, session: "mypy" }
          - { python-version: "3.10", os: ubuntu-latest, session: "mypy" }
          - { python-version: "3.13", os: ubuntu-latest, session: "tests" }
          - { python-version: "3.12", os: ubuntu-latest, session: "tests" }
          - { python-version: "3.11", os: ubuntu-latest, session: "tests" }
          - { python-version: "3.10", os: ubuntu-latest, session: "tests" }
          - { python-version: "3.13", os: windows-latest, session: "tests" }
          - { python-version: "3.13", os: macos-latest, session: "tests" }
          - { python-version: "3.13", os: ubuntu-latest, session: "typeguard" }
          - { python-version: "3.13", os: ubuntu-latest, session: "xdoctest" }
          - { python-version: "3.13", os: ubuntu-latest, session: "docs-build" }

    env:
      NOXSESSION: ${{ matrix.session }}

    steps:
      - name: Check out the repository
        uses: actions/checkout@v6.0.0

      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v6.1.0
        with:
          python-version: ${{ matrix.python-version }}

      - name: Upgrade pip
        run: |
          pip install --constraint=.github/workflows/constraints.txt pip
          pip --version

      - name: Install Poetry
        run: |
          pip install --constraint=.github/workflows/constraints.txt poetry
          poetry --version
          poetry self add poetry-plugin-export
          poetry self show plugins

      - name: Install Nox
        run: |
          pip install --constraint=.github/workflows/constraints.txt nox nox-poetry
          nox --version

      - name: Compute pre-commit cache key
        if: matrix.session == 'pre-commit'
        id: pre-commit-cache
        run: |
          echo "result=${{ runner.os }}-$(python --version | cut -d ' ' -f 2)" >> $GITHUB_OUTPUT

      - name: Restore pre-commit cache
        uses: actions/cache@v4
        if: matrix.session == 'pre-commit'
        with:
          path: ~/.cache/pre-commit
          key: ${{ steps.pre-commit-cache.outputs.result }}-${{ hashFiles('.pre-commit-config.yaml') }}
          restore-keys: |
            ${{ steps.pre-commit-cache.outputs.result }}-

      - name: Run Nox
        run: |
          nox --force-color --python=${{ matrix.python-version }}

      - name: Upload coverage data
        if: always() && matrix.session == 'tests'
        uses: actions/upload-artifact@v5.0.0
        with:
          name: coverage-data-${{ matrix.python-version }}-${{ matrix.os }}
          path: ".coverage.*"
          include-hidden-files: true

      - name: Upload documentation
        if: matrix.session == 'docs-build'
        uses: actions/upload-artifact@v5.0.0
        with:
          name: docs
          path: docs/_build

  coverage:
    runs-on: ubuntu-latest
    needs: tests
    steps:
      - name: Check out the repository
        uses: actions/checkout@v6.0.0

      - name: Set up Python
        uses: actions/setup-python@v6.1.0
        with:
          python-version: "3.13"

      - name: Upgrade pip
        run: |
          pip install --constraint=.github/workflows/constraints.txt pip
          pip --version

      - name: Install Poetry
        run: |
          pip install --constraint=.github/workflows/constraints.txt poetry
          poetry --version
          poetry self add poetry-plugin-export
          poetry self show plugins

      - name: Install Nox
        run: |
          pip install --constraint=.github/workflows/constraints.txt nox nox-poetry
          nox --version

      - name: Download coverage data
        uses: actions/download-artifact@v6.0.0
        with:
          pattern: coverage-data-*
          merge-multiple: true

      - name: Combine coverage data and display human readable report
        run: |
          nox --force-color --session=coverage

      - name: Create coverage report
        run: |
          nox --force-color --session=coverage -- xml

      - name: Upload coverage report
        uses: codecov/codecov-action@v5.5.1
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
