name: PR Job
on: [push, pull_request, workflow_dispatch]

env:
  DEFAULT_PYTHON_VERSION: 3.13

jobs:
  linter:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 0
      - uses: actions/setup-python@v6
        id: setup-python
        with:
          python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
      - name: Install poetry
        uses: snok/install-poetry@v1
        with:
          virtualenvs-create: true
          virtualenvs-in-project: true
          virtualenvs-path: .venv
          installer-parallel: true
      - name: Load cached venv
        id: cached-poetry-dependencies
        uses: actions/cache@v5
        with:
          path: .venv
          key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}
      - name: Install dependencies
        if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
        run: poetry install
      - name: ruff check
        continue-on-error: true
        run: poetry run ruff check
      - name: ruff format
        continue-on-error: true
        run: poetry run ruff check
      - name: pylint
        continue-on-error: true
        run: poetry run pylint .
      - name: black
        run: poetry run black --check .
      - name: isort
        run: poetry run isort --check .
      - name: doc8
        run: poetry run doc8 README.rst --ignore D001

  verify:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [windows-latest, ubuntu-latest]
        python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14" ]

    steps:
      - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
      - run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
      - name: Check out repository code
        uses: actions/checkout@v6
        with:
          fetch-depth: 0
      - run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
      - uses: actions/setup-python@v6
        id: setup-python
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install poetry
        uses: snok/install-poetry@v1
        with:
          virtualenvs-create: true
          virtualenvs-in-project: true
          virtualenvs-path: .venv
          installer-parallel: true
      - name: Load cached venv
        id: cached-poetry-dependencies
        uses: actions/cache@v5
        with:
          path: .venv
          key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}
      - name: Install dependencies
        if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
        shell: bash
        run: poetry install
      - name: Run tests
        shell: bash
        run: |
          echo "ARTIFACT_NAME=coverage_${{ runner.os }}-py-${{ matrix.python-version }}" | sed 's|\\.\\*||g' >> "$GITHUB_ENV"
          poetry run pytest -n auto --cov-context test --cov --cov-report=xml tests
      - name: Upload coverage artifact
        uses: actions/upload-artifact@v6
        with:
          include-hidden-files: true
          if-no-files-found: error
          name: ${{ env.ARTIFACT_NAME }}
          path: .coverage
          retention-days: 1
      - run: echo "🍏 This job's status is ${{ job.status }}."

  coverage:
    runs-on: ubuntu-latest
    needs: verify
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 0
      - uses: actions/setup-python@v6
        id: setup-python
        with:
          python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
      - name: Install poetry
        uses: snok/install-poetry@v1
        with:
          virtualenvs-create: true
          virtualenvs-in-project: true
          virtualenvs-path: .venv
          installer-parallel: true
      - name: Load cached venv
        id: cached-poetry-dependencies
        uses: actions/cache@v5
        with:
          path: .venv
          key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}
      - name: Install dependencies
        if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
        shell: bash
        run: poetry install
      - name: Download artifacts
        uses: actions/download-artifact@v7
        with:
          path: downloaded_artifacts
      - name: Clean up temporary artifacts
        uses: geekyeggo/delete-artifact@v5
        with:
          name: coverage_*
      - name: Combine coverage.py
        run: |
          poetry run coverage combine $(find downloaded_artifacts/ -type f | xargs)
          poetry run coverage xml
          poetry run coverage html
          poetry run coverage report --format=markdown >> $GITHUB_STEP_SUMMARY
          cp coverage.xml htmlcov/coverage.xml
          cp .coverage htmlcov/.coverage
      - name: Complete coverage
        run: |
          poetry run diff-cover coverage.xml --include-untracked --format github-annotations:warning
          poetry run diff-quality --violations flake8 --include-untracked
          poetry run diff-quality --violations pylint --include-untracked
      - name: Upload single coverage artifact
        uses: actions/upload-artifact@v6
        with:
          include-hidden-files: true
          if-no-files-found: error
          name: htmlcov
          path: htmlcov
          # Retention days for main branch is 90 days, for other branches is 1 day
          retention-days: ${{ github.ref == 'refs/heads/main' && 90 || 1 }}
