name: '🔎 Python Tests'

on:
  pull_request:
    branches:
      - main
      - v*.*.*
      - epic-*

concurrency:
  group: ci-tests-${{ github.ref }}-pytest
  cancel-in-progress: true

jobs:
  python-tests:

    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: [ "3.9", "3.12" ]

    steps:
      - name: Checkout repo
        uses: actions/checkout@v4

      - name: Install latest Rust stable
        uses: dtolnay/rust-toolchain@stable

      - id: setup_python
        name: Set up Python ${{ matrix.python-version }} Environment
        uses: actions/setup-python@v4
        with:
          python-version: ${{ matrix.python-version }}

      - id: python_cache
        name: Retrieve Cached Python Dependencies
        uses: actions/cache@v3
        with:
          path: ${{ env.pythonLocation }}
          key: ${{ runner.os }}-pip-${{ steps.setup_python.outputs.python-version }}-${{ hashFiles('dev-requirements.txt', 'requirements.txt') }}

      - name: Upgrade pip
        if: steps.python_cache.outputs.cache-hit != 'true'
        run: python -m pip install --upgrade pip

      - name: Install packages (incl. updated code)
        run: pip install .[dev]

      - name: Check CLI Entrypoint
        run: nucypher --help

      - name: Check Python Entrypoint
        run: python -c "import nucypher; print(nucypher.__version__)"

      # Unit tests
      - name: Unit Tests (Coverage)
        if: matrix.python-version == '3.12'
        run: |
          coverage run --data-file=unit_data -m pytest tests/unit
          coverage xml -i --data-file=unit_data -o unit-coverage.xml

      - name: Unit Tests
        if: matrix.python-version != '3.12'
        run: python -m pytest tests/unit

      # Integration tests
      - name: Integration Tests (Coverage)
        if: matrix.python-version == '3.12'
        run: |
          coverage run --data-file=integration_data -m pytest tests/integration
          coverage xml -i --data-file=integration_data -o integration-coverage.xml

      - name: Integration Tests
        if: matrix.python-version != '3.12'
        run: python -m pytest tests/integration

      # Acceptance tests
      - name: Agents Tests (Coverage)
        if: matrix.python-version == '3.12'
        working-directory: tests/acceptance
        run: |
          coverage run --data-file=acceptance_agent_data -m pytest agents
          coverage xml -i --data-file=acceptance_agent_data -o acceptance-agents-coverage.xml

      - name: Agents Tests
        if: matrix.python-version != '3.12'
        working-directory: tests/acceptance
        run: python -m pytest agents

      - name: Actors Tests (Coverage)
        if: matrix.python-version == '3.12'
        working-directory: tests/acceptance
        run: |
          coverage run --data-file=acceptance_actors_data -m pytest actors
          coverage xml -i --data-file=acceptance_actors_data -o acceptance-actors-coverage.xml

      - name: Actors Tests
        if: matrix.python-version != '3.12'
        working-directory: tests/acceptance
        run: python -m pytest actors


      - name: Conditions Tests (Coverage)
        if: matrix.python-version == '3.12'
        working-directory: tests/acceptance
        run: |
          coverage run --data-file=acceptance_conditions_data -m pytest conditions
          coverage xml -i --data-file=acceptance_conditions_data -o acceptance-conditions-coverage.xml

      - name: Conditions Tests
        if: matrix.python-version != '3.12'
        working-directory: tests/acceptance
        run: python -m pytest conditions


      - name: Characters Tests (Coverage)
        if: matrix.python-version == '3.12'
        working-directory: tests/acceptance
        run: |
          coverage run --data-file=acceptance_characters_data -m pytest characters
          coverage xml -i --data-file=acceptance_characters_data -o acceptance-characters-coverage.xml

      - name: Characters Tests
        if: matrix.python-version != '3.12'
        working-directory: tests/acceptance
        run: python -m pytest characters


      - name: CLI Tests (Coverage)
        if: matrix.python-version == '3.12'
        working-directory: tests/acceptance
        run: |
          coverage run --data-file=acceptance_cli_data -m pytest cli
          coverage xml -i --data-file=acceptance_cli_data -o acceptance-cli-coverage.xml

      - name: CLI Tests
        if: matrix.python-version != '3.12'
        working-directory: tests/acceptance
        run: python -m pytest cli


      # Only upload coverage files after all tests have passed
      - name: Upload unit tests coverage to Codecov
        if: matrix.python-version == '3.12'
        uses: codecov/codecov-action@v4
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          files: unit-coverage.xml
          flags: unit
          fail_ci_if_error: true
          verbose: true

      - name: Upload integration tests coverage to Codecov
        if: matrix.python-version == '3.12'
        uses: codecov/codecov-action@v4
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          files: integration-coverage.xml
          flags: integration
          fail_ci_if_error: true
          verbose: true

      - name: Upload acceptance tests coverage to Codecov
        if: matrix.python-version == '3.12'
        uses: codecov/codecov-action@v4
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          directory: tests/acceptance
          files: acceptance-agents-coverage.xml, acceptance-actors-coverage.xml, acceptance-conditions-coverage.xml, acceptance-characters-coverage.xml, acceptance-cli-coverage.xml
          flags: acceptance
          fail_ci_if_error: true
          verbose: true
