name: Tests

on:
  pull_request:
    branches: [main,v1.0]
  push:
    branches: [main]

jobs:
  style:
    name: Check the code style
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
    - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
      with:
        python-version: "3.13"
    - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
      with:
        path: ~/.cache/pre-commit
        key: pre-commit-3|${{ env.pythonLocation }}|${{ hashFiles('.pre-commit-config.yaml') }}
    - run: python -m pip install pre-commit
    - run: pre-commit run --all-files --show-diff-on-failure --color=always

  tests:
    name: Run the tests
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.10", "3.13"]
    steps:
    - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
      with:
        python-version: ${{ matrix.python-version }}
        cache: 'pip'
        cache-dependency-path: 'pyproject.toml'
    - name: Free disk space
      run: |
        set -eux
        sudo rm -rf /usr/share/dotnet || true
        sudo rm -rf /opt/ghc || true
        sudo rm -rf /usr/local/lib/android || true
        sudo apt-get clean
        df -h
    - name: Install Ollama
      run: |
        curl -fsSL https://ollama.com/install.sh | sh
        ollama --version
        ollama serve &
        # Wait for the server to become available
        for i in $(seq 1 30); do
          ollama list && break || sleep 2
        done
        ollama pull tinyllama
        ollama pull moondream
    - name: Set up test environment
      run: |
        python -m pip install --upgrade pip
        pip install uv
        uv sync --no-group test-gpu --extra test
    - name: cache HuggingFace models
      uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
      with:
        path: ~/.cache/huggingface
        key: hf-${{ runner.os }}-${{ hashFiles('**/pyproject.toml') }}
        restore-keys: |
          hf-${{ runner.os }}-
    - name: Create matrix id
      id: matrix-id
      env:
        MATRIX_CONTEXT: ${{ toJson(matrix) }}
      run: |
        echo $MATRIX_CONTEXT
        export MATRIX_ID=`echo $MATRIX_CONTEXT | md5sum | cut -c 1-32`
        echo $MATRIX_ID
        echo "::set-output name=id::$MATRIX_ID"
    - name: Run tests
      run: |
        rm -f .coverage*
        uv run coverage erase
        uv run python -m coverage run --branch --source=outlines --parallel-mode -m pytest --continue-on-collection-errors -m 'not api_call'
    - name: Upload coverage data
      uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
      with:
        name: coverage-data-${{ matrix.python-version }}
        path: .coverage.*
        if-no-files-found: ignore
        include-hidden-files: true

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

    steps:
      - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
        with:
          fetch-depth: 0

      - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
        with:
          cache: pip
          python-version: "3.11"

      - name: Set up environment
        run: |
          pip install --upgrade "coverage[toml]>=5.1" diff-cover

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

      - name: Combine coverage & fail if it's <100%.
        run: |
          python -m coverage combine
          python -m coverage html --skip-covered --skip-empty
          python -m coverage xml
          python -m coverage report --fail-under=100 || (python -m coverage report && exit 1)

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

  build-wheel:
    name: Build Wheel and Test SDist
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
      - name: Build SDist and Wheel
        run: ./.github/scripts/build_sdist_and_wheel.sh