name: Test

on:
  push:
    branches:
      - "**"
    paths-ignore:
      - ".github/workflows/docs.yml"
      - ".github/workflows/wheels*"
      - ".gitmodules"
      - "docs/**"
      - "wheels/**"
  pull_request:
    paths-ignore:
      - ".github/workflows/docs.yml"
      - ".github/workflows/wheels*"
      - ".gitmodules"
      - "docs/**"
      - "wheels/**"
  workflow_dispatch:

permissions:
  contents: read

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

env:
  COVERAGE_CORE: sysmon
  FORCE_COLOR: 1
  PIP_DISABLE_PIP_VERSION_CHECK: 1

jobs:
  build:

    strategy:
      fail-fast: false
      matrix:
        os: [
          "macos-latest",
          "ubuntu-latest",
        ]
        python-version: [
          "pypy3.11",
          "3.15t",
          "3.15",
          "3.14t",
          "3.14",
          "3.13t",
          "3.13",
          "3.12",
          "3.11",
          "3.10",
        ]
        include:
        - { python-version: "3.12", PYTHONOPTIMIZE: 1, REVERSE: "--reverse" }
        - { python-version: "3.11", PYTHONOPTIMIZE: 2 }
        # Free-threaded
        - { python-version: "3.15t", disable-gil: true }
        - { python-version: "3.14t", disable-gil: true }
        - { python-version: "3.13t", disable-gil: true }
        # Intel
        - { os: "macos-26-intel", python-version: "3.10" }
        exclude:
        - { os: "macos-latest", python-version: "3.10" }

    runs-on: ${{ matrix.os }}
    name: ${{ matrix.os }} Python ${{ matrix.python-version }}

    steps:
    - uses: actions/checkout@v6
      with:
        persist-credentials: false

    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v6
      with:
        python-version: ${{ matrix.python-version }}
        allow-prereleases: true
        cache: pip
        cache-dependency-path: |
          ".ci/*.sh"
          "pyproject.toml"

    - name: Set PYTHON_GIL
      if: "${{ matrix.disable-gil }}"
      run: |
        echo "PYTHON_GIL=0" >> $GITHUB_ENV

    - name: Build system information
      run: python3 .github/workflows/system-info.py

    - name: Cache libavif
      if: startsWith(matrix.os, 'ubuntu')
      uses: actions/cache@v5
      id: cache-libavif
      with:
        path: ~/cache-libavif
        key: ${{ runner.os }}-libavif-${{ hashFiles('depends/install_libavif.sh', 'depends/libavif-svt4.patch') }}

    - name: Cache libimagequant
      if: startsWith(matrix.os, 'ubuntu')
      uses: actions/cache@v5
      id: cache-libimagequant
      with:
        path: ~/cache-libimagequant
        key: ${{ runner.os }}-libimagequant-${{ hashFiles('depends/install_imagequant.sh') }}

    - name: Cache libwebp
      if: startsWith(matrix.os, 'ubuntu')
      uses: actions/cache@v5
      id: cache-libwebp
      with:
        path: ~/cache-libwebp
        key: ${{ runner.os }}-libwebp-${{ hashFiles('depends/install_webp.sh') }}

    - name: Install Linux dependencies
      if: startsWith(matrix.os, 'ubuntu')
      run: |
        .ci/install.sh
      env:
        GHA_PYTHON_VERSION: ${{ matrix.python-version }}
        GHA_LIBAVIF_CACHE_HIT: ${{ steps.cache-libavif.outputs.cache-hit }}
        GHA_LIBIMAGEQUANT_CACHE_HIT: ${{ steps.cache-libimagequant.outputs.cache-hit }}
        GHA_LIBWEBP_CACHE_HIT: ${{ steps.cache-libwebp.outputs.cache-hit }}

    - name: Install macOS dependencies
      if: startsWith(matrix.os, 'macOS')
      run: |
        .github/workflows/macos-install.sh
      env:
        GHA_PYTHON_VERSION: ${{ matrix.python-version }}

    - name: Register gcc problem matcher
      if: "matrix.os == 'ubuntu-latest' && matrix.python-version == '3.14'"
      run: echo "::add-matcher::.github/problem-matchers/gcc.json"

    - name: Build
      run: |
        .ci/build.sh

    - name: Test
      run: |
        if [ $REVERSE ]; then
          python3 -m pip install pytest-reverse
        fi
        if [ "${{ matrix.os }}" = "ubuntu-latest" ]; then
          xvfb-run -s '-screen 0 1024x768x24' sway&
          export WAYLAND_DISPLAY=wayland-1
          .ci/test.sh
        else
          .ci/test.sh
        fi
      env:
        PYTHONOPTIMIZE: ${{ matrix.PYTHONOPTIMIZE }}
        REVERSE: ${{ matrix.REVERSE }}

    - name: Prepare to upload errors
      if: failure()
      run: |
        mkdir -p Tests/errors

    - name: Upload errors
      uses: actions/upload-artifact@v6
      if: failure()
      with:
        name: errors
        path: Tests/errors

    - name: After success
      run: |
        .ci/after_success.sh

    - name: Upload coverage
      uses: codecov/codecov-action@v5
      with:
        flags: ${{ matrix.os == 'ubuntu-latest' && 'GHA_Ubuntu' || 'GHA_macOS' }}
        name: ${{ matrix.os }} Python ${{ matrix.python-version }}
        token: ${{ secrets.CODECOV_ORG_TOKEN }}

  success:
    permissions:
      contents: none
    needs: build
    runs-on: ubuntu-latest
    name: Test Successful
    steps:
      - name: Success
        run: echo Test Successful
