---
name: CI

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

env:
  FORCE_COLOR: "1" # Make tools pretty.
  PIP_DISABLE_PIP_VERSION_CHECK: "1"
  PIP_NO_PYTHON_VERSION_WARNING: "1"

permissions: {}


jobs:
  build-package:
    name: Build & verify package
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
          persist-credentials: false

      - uses: hynek/build-and-inspect-python-package@v2
        id: baipp

    outputs:
      # Used to define the matrix for tests below. The value is based on
      # packaging metadata (trove classifiers).
      python-versions: ${{ steps.baipp.outputs.supported_python_classifiers_json_array }}


  tests:
    name: Tests & Mypy API on ${{ matrix.python-version }}
    runs-on: ubuntu-latest
    needs: build-package

    strategy:
      fail-fast: false
      matrix:
        # Created by the build-and-inspect-python-package action above.
        python-version: ${{ fromJson(needs.build-package.outputs.python-versions) }}

    env:
      PYTHON: ${{ matrix.python-version }}

    steps:
      - name: Download pre-built packages
        uses: actions/download-artifact@v4
        with:
          name: Packages
          path: dist
      - run: |
          tar xf dist/*.tar.gz --strip-components=1
          rm -rf src
      - uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
          allow-prereleases: true
      - uses: hynek/setup-cached-uv@v2

      - name: Run tests
        run: >
          uvx --with tox-uv tox run
          --installpkg dist/*.whl
          -f py${PYTHON//./}-tests

      - name: Upload coverage data
        uses: actions/upload-artifact@v4
        with:
          name: coverage-data-${{ matrix.python-version }}
          path: .coverage.*
          include-hidden-files: true
          if-no-files-found: ignore

      - name: Check public API with Mypy
        run: >
          uvx --with tox-uv tox run
          --installpkg dist/*.whl
          -e py${PYTHON//./}-mypy


  coverage:
    name: Ensure 100% test coverage
    runs-on: ubuntu-latest
    needs: tests
    if: always()

    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false
      - uses: actions/setup-python@v5
        with:
          python-version-file: .python-version-default
      - uses: hynek/setup-cached-uv@v2

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

      - name: Combine coverage and fail if it's <100%.
        run: |
          uv tool install coverage

          coverage combine
          coverage html --skip-covered --skip-empty

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

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

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


  system-package:
    name: Install & test with system package of Argon2
    runs-on: ubuntu-latest
    needs: build-package

    steps:
      - name: Download pre-built packages
        uses: actions/download-artifact@v4
        with:
          name: Packages
          path: dist
      - run: tar xf dist/*.tar.gz --strip-components=1
      - uses: actions/setup-python@v5
        with:
          python-version-file: .python-version-default

      - name: Install dependencies
        run: |
          sudo apt-get install libargon2-1 libargon2-dev
          python -VV
          python -Im site
          python -Im pip install --upgrade tox

      - run: python -Im tox run -e system-argon2


  mypy-pkg:
    name: Mypy Codebase
    runs-on: ubuntu-latest
    needs: build-package

    steps:
      - name: Download pre-built packages
        uses: actions/download-artifact@v4
        with:
          name: Packages
          path: dist
      - run: tar xf dist/*.tar.gz --strip-components=1
      - uses: actions/setup-python@v5
        with:
          python-version-file: .python-version-default
      - uses: hynek/setup-cached-uv@v2

      - run: >
          uvx --with tox-uv
          tox run -e mypy-pkg

  pyright:
    name: Pyright Codebase
    runs-on: ubuntu-latest
    needs: build-package

    steps:
      - name: Download pre-built packages
        uses: actions/download-artifact@v4
        with:
          name: Packages
          path: dist
      - run: tar xf dist/*.tar.gz --strip-components=1
      - uses: actions/setup-python@v5
        with:
          python-version-file: .python-version-default
      - uses: hynek/setup-cached-uv@v2

      - run: |
          uv venv
          uv pip install . --group typing
          echo "$PWD/.venv/bin" >> $GITHUB_PATH
      - uses: jakebailey/pyright-action@b5d50e5cde6547546a5c4ac92e416a8c2c1a1dfe  # v2.3.2


  docs:
    name: Run doctests
    needs: build-package
    runs-on: ubuntu-latest
    steps:
      - name: Download pre-built packages
        uses: actions/download-artifact@v4
        with:
          name: Packages
          path: dist
      - run: tar xf dist/*.tar.gz --strip-components=1
      - uses: hynek/setup-cached-uv@v2

      - run: >
          uvx --with tox-uv
          tox run -e docs-doctests


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

    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false
      - uses: actions/setup-python@v5
        with:
          python-version-file: .python-version-default

      - name: Install in dev mode and run CLI
        run: |
         python -Im pip install -e . --group dev
         python -Im argon2 -n 1 -t 1 -m 8 -p 1


  required-checks-pass:
    if: always()
    name: Ensure everything required is passing for branch protection
    runs-on: ubuntu-latest
    needs:
      - coverage
      - mypy-pkg
      - pyright
      - docs
      - install-dev
      - system-package

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