---
name: CI

on:
  merge_group:
  push:
    branches: [main]
    tags: ["*"]
  pull_request:
    branches: [main]
  workflow_dispatch:

env:
  FORCE_COLOR: "1" # Make tools pretty.
  PIP_DISABLE_PIP_VERSION_CHECK: "1"
  PIP_NO_PYTHON_VERSION_WARNING: "1"
  # Use oldest version used in doctests / examples.
  SETUPTOOLS_SCM_PRETEND_VERSION: "19.2.0"

permissions: {}

jobs:
  tests:
    name: Tests & Mypy on ${{ matrix.python-version }}
    runs-on: ubuntu-latest

    strategy:
      fail-fast: false
      matrix:
        python-version:
          - "3.7"
          - "3.8"
          - "3.9"
          - "3.10"
          - "3.11"
          - "3.12"
          # - "pypy-3.7"
          - "pypy-3.8"
          - "pypy-3.9"
          - "pypy-3.10"

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v4
        with:
          python-version: ${{ matrix.python-version }}
          allow-prereleases: true
          cache: pip

      - name: Prepare tox
        run: |
          V=${{ matrix.python-version }}

          if [[ "$V" = pypy-* ]]; then
            V=pypy3
            IS_PYPY=1
          else
            V=py$(echo $V | tr -d .)
            IS_PYPY=0
          fi

          echo IS_PYPY=$IS_PYPY >>$GITHUB_ENV
          echo TOX_PYTHON=$V >>$GITHUB_ENV

          python -Im pip install tox

      - run: python -Im tox run -e ${{ env.TOX_PYTHON }}-tests
      - run: python -Im tox run -e ${{ env.TOX_PYTHON }}-mypy
        if: env.IS_PYPY == '0' && matrix.python-version != '3.7'

      - name: Upload coverage data
        uses: actions/upload-artifact@v3
        with:
          name: coverage-data
          path: .coverage.*
          if-no-files-found: ignore

  coverage:
    name: Combine & check coverage.
    runs-on: ubuntu-latest
    needs: tests

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v4
        with:
          python-version-file: .python-version-default
          cache: pip

      - name: Download coverage data
        uses: actions/download-artifact@v3
        with:
          name: coverage-data

      - name: Combine coverage & fail if it's <100%.
        run: |
          python -Im pip install coverage[toml]

          python -Im coverage combine
          python -Im coverage html --skip-covered --skip-empty

          # Report and write to summary.
          python -Im coverage report --format=markdown >> $GITHUB_STEP_SUMMARY

          # Report again and fail if under 100%.
          python -Im coverage report --fail-under=100

      - name: Upload HTML report if check failed.
        uses: actions/upload-artifact@v3
        with:
          name: html-report
          path: htmlcov
        if: ${{ failure() }}

  docs:
    name: Build docs & run doctests
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v4
        with:
          # Keep in sync with tox/docs and .readthedocs.yaml.
          python-version: "3.12"
          cache: pip

      - run: python -Im pip install tox
      - run: python -Im tox run -e docs,changelog

  pyright:
    name: Check types using pyright
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v4
        with:
          python-version-file: .python-version-default
          cache: pip

      - run: python -Im pip install tox
      - run: python -Im tox run -e pyright

  install-dev:
    name: Verify dev env
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest]

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v4
        with:
          python-version-file: .python-version-default
          cache: pip

      - name: Install in dev mode & import
        run: |
          python -Im pip install -e .[dev]
          python -Ic 'import attr; print(attr.__version__)'
          python -Ic 'import attrs; print(attrs.__version__)'

  # Ensure everything required is passing for branch protection.
  required-checks-pass:
    if: always()

    needs:
      - coverage
      - docs
      - install-dev
      - pyright

    runs-on: ubuntu-latest

    steps:
      - name: Decide whether the needed jobs succeeded or failed
        uses: re-actors/alls-green@release/v1
        with:
          jobs: ${{ toJSON(needs) }}
