# This workflow runs our usual CI jobs: testing with pytest, profiling,
# and coverage checks for PST
# IMPORTANT: if you make changes to this workflow, you will need to open a follow-up
# PR after merge to update the action SHA in the publish workflow

name: continuous-integration

# Concurrency group that uses the workflow name and PR number if available
# or commit SHA as a fallback. If a new build is triggered under that
# concurrency group while a previous build is running it will be canceled.
# Repeated pushes to a PR will cancel all previous builds, while multiple
# merges to main will not cancel.
concurrency:
  group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
  cancel-in-progress: true

env:
  FORCE_COLOR: "1" # Make tools pretty
  DEFAULT_PYTHON_VERSION: "3.14" # keep in sync with tox.ini
  PIP_DISABLE_PIP_VERSION_CHECK: "1" # Don't check for pip updates

permissions: {}

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - "*"
  # allows this to be used as a composite action in other workflows
  workflow_call:
  # allow manual triggering of the workflow, while debugging
  workflow_dispatch:

jobs:
  # Run our test suite on various combinations of OS & Python versions
  run-pytest:
    strategy:
      fail-fast: true
      matrix:
        # https://github.com/actions/runner-images
        # macos-14==latest
        # ubuntu-24.04==latest
        # windows-2022==latest
        os: ["ubuntu-latest", "ubuntu-22.04", "macos-14", "windows-latest"]
        python-version: ["3.10", "3.14"]
        sphinx-version: [""]
        include:
          # oldest Python version with the oldest Sphinx version
          - os: ubuntu-latest
            python-version: "3.10"
            sphinx-version: "7.0"
            # newest Python version with the newest Sphinx version
          - os: ubuntu-latest
            python-version: "3.14"
            # Sphinx HEAD
            sphinx-version: "dev"
        exclude:
          # Python 3.10 is not supported on arm64 darwin - https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json
          - os: macos-14
            python-version: "3.10"
          # do not need all the tests so will limit to the latest versions of Python
          - os: ubuntu-24.04
            python-version: "3.10"
          - os: ubuntu-24.04
            python-version: "3.10"
    runs-on: ${{ matrix.os }}
    steps:
      - name: "Checkout repository 🛎"
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
        with:
          persist-credentials: false

      - name: "Setup CI environment 🛠"
        # Important: make sure to update the SHA after making any changes to the set-dev-env action
        uses: pydata/pydata-sphinx-theme/.github/actions/set-dev-env@e8db643b990df73812cf9397bc0f8cfa1164e4d3
        with:
          python-version: ${{ matrix.python-version }}
          pandoc: true

      - name: "Cache Playwright browsers 🎭"
        uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
        with:
          path: |
            ~/.cache/ms-playwright
            ~/Library/Caches/ms-playwright
            ~\AppData\Local\ms-playwright
          key: playwright-${{ runner.os }}-${{ hashFiles('pyproject.toml') }}

      - name: "Run tests"
        shell: bash
        run: |
          # this will compile the assets and translations then run the tests
          # check if there is a specific Sphinx version to test with
          # example substitution: tox run -e compile-assets,i18n-compile,py310-sphinx61-tests
          if [ -n "${{matrix.sphinx-version}}" ]; then
            python -Im tox run -e compile-assets,i18n-compile,py$(echo ${{ matrix.python-version }} | tr -d .)-sphinx$(echo ${{ matrix.sphinx-version }} | tr -d .)-tests
          # if not we use the default version
          # example substitution: tox run -e compile-assets,i18n-compile,py310-tests
          else
            python -Im tox run -e compile-assets,i18n-compile,py$(echo ${{ matrix.python-version }} | tr -d .)-tests
          fi

      - name: "Upload coverage data to GH artifacts 📤"
        if: matrix.python-version == '3.14' && matrix.os == 'ubuntu-latest' && matrix.sphinx-version == 'dev'
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f
        with:
          name: coverage-data-${{ matrix.python-version }}
          path: .coverage
          if-no-files-found: ignore
          include-hidden-files: true

      - name: "Upload Playwright traces, if any 🐾"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v4.7.0.0
        if: ${{ failure() }}
        with:
          name: playwright-traces-${{ matrix.os }}-${{ matrix.python-version }}
          path: test-results/

  coverage:
    name: "check coverage"
    needs: run-pytest
    runs-on: ubuntu-latest
    # avoid running this on schedule, releases, workflow_call, or workflow_dispatch
    if: github.event_name != 'schedule' && github.event_name != 'release' && github.event_name != 'workflow_call' && github.event_name != 'workflow_dispatch'
    permissions:
      contents: write
      pull-requests: write
    steps:
      - name: "Checkout repository 🛎"
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
        with:
          persist-credentials: false

      - name: "Setup CI environment 🛠"
        uses: pydata/pydata-sphinx-theme/.github/actions/set-dev-env@e8db643b990df73812cf9397bc0f8cfa1164e4d3
        with:
          python-version: ${{ env.DEFAULT_PYTHON_VERSION }}

      - run: python -Im pip install --upgrade coverage[toml]

      - name: "Download coverage data 📥"
        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
        with:
          pattern: coverage-data-*
          merge-multiple: true

      - name: "Get coverage data & fail if it's <80%"
        run: |
          # if we decide to check cov across versions and combine
          # 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 80%.
          python -Im coverage report --fail-under=80

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

      # seems we need to call this from the main CI workflow first
      - name: "Coverage comment 💬"
        uses: py-cov-action/python-coverage-comment-action@7188638f871f721a365d644f505d1ff3df20d683 # 3.38.0
        id: coverage_comment
        with:
          GITHUB_TOKEN: ${{ github.token }}

      - name: "Store Pull Request comment to be posted 📤"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f
        if: steps.coverage_comment.outputs.COMMENT_FILE_WRITTEN == 'true'
        with:
          # leave default names
          name: python-coverage-comment-action
          path: python-coverage-comment-action.txt

  profiling:
    needs: [run-pytest]
    runs-on: ubuntu-latest
    steps:
      - name: "Checkout repository 🛎"
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
        with:
          persist-credentials: false

      - name: "Setup CI environment 🛠"
        uses: pydata/pydata-sphinx-theme/.github/actions/set-dev-env@e8db643b990df73812cf9397bc0f8cfa1164e4d3
        with:
          # 3.14 is not supported by py-spy yet
          python-version: "3.13"

      - name: "Run profiling with py-spy 🕵️‍♂️"
        # profiling needs to be run as sudo
        run: python -m tox run -e py313-profile-docs -- -o docbuild_profile.svg
        continue-on-error: true

      - name: "Upload profiling data to GH artifacts 📤"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f
        with:
          name: profile-results
          path: docbuild_profile.svg
          if-no-files-found: ignore

  # Calling the coverage-comment action from the main CI workflow
  # we might want to pin the SHA once merged
  coverage-comment:
    # Important: make sure to update the SHA after making any changes to the coverage workflow
    # removing pin to test changes
    uses: ./.github/workflows/coverage.yml
    needs: [coverage]
    # ensures this runs even if the coverage step does not continue - e.g. the
    # default coverage action will fail at first for external PRs, this is a workaround
    # to ensure the comment is posted
    if: ${{ github.event.name == 'pull_request'}}
    with:
      # this is the workflow run ID of the `CI.yml` workflow
      workflow_run_id: ${{ github.event.workflow_run.id }}
    permissions:
      contents: write
      pull-requests: write
      actions: read
