name: Python tests
# This workflow is triggered on pushes and PRs to the repository.
# Only run if we changed a Python file
on:
  push:
    branches:
      - dev
      # https://docs.renovatebot.com/key-concepts/automerge/#branch-vs-pr-automerging
      - "renovate/**" # branches Renovate creates
    paths-ignore:
      - "docs/**"
      - "CHANGELOG.md"
  pull_request:
    paths-ignore:
      - "docs/**"
      - "CHANGELOG.md"
      # ignore github workflows except for the current one
      - ".github/**"
      - "!.github/workflows/pytest.yml"
  release:
    types: [published]
  workflow_dispatch:

# Cancel if a newer run with the same workflow name is queued
concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

env:
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

jobs:
  setup:
    runs-on: "ubuntu-latest"
    strategy:
      matrix:
        python-version: ["3.8", "3.12"]
        runner: ["ubuntu-latest"]
        include:
          - python-version: "3.8"
            runner: "ubuntu-20.04"

    steps:
      - name: Check conditions
        id: conditions
        run: echo "run-tests=${{ github.ref == 'refs/heads/main' || (matrix.runner == 'ubuntu-20.04' && matrix.python-version == '3.8') }}" >> "$GITHUB_OUTPUT"

    outputs:
      python-version: ${{ matrix.python-version }}
      runner: ${{ matrix.runner }}
      run-tests: ${{ steps.conditions.outputs.run-tests }}

  # create a test matrix based on all python files in /tests
  list_tests:
    name: Get test file matrix
    runs-on: "ubuntu-latest"
    steps:
      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
        name: Check out source-code repository

      - name: List tests
        id: list_tests
        run: |
          echo "tests=$(find tests -type f -name "test_*.py" | tac | sed 's/tests\///g'  | jq -R -s -c '{test: (split("\n")[:-1])}')" >> $GITHUB_OUTPUT
    outputs:
      tests: ${{ steps.list_tests.outputs.tests }}

  test:
    name: Run ${{matrix.test}} with Python ${{ needs.setup.outputs.python-version }} on ${{ needs.setup.outputs.runner }}
    needs: [setup, list_tests]
    if: ${{ needs.setup.outputs.run-tests }}
    runs-on:
      - runs-on=${{ github.run_id }}-run-test
      - runner=4cpu-linux-x64
    strategy:
      matrix: ${{ fromJson(needs.list_tests.outputs.tests) }}
      fail-fast: false # run all tests even if one fails
    steps:
      - name: go to subdirectory and change nextflow workdir
        run: |
          mkdir -p pytest
          cd pytest
          export NXF_WORK=$(pwd)

      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
        name: Check out source-code repository

      - name: Set up Python ${{ needs.setup.outputs.python-version }}
        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
        with:
          python-version: ${{ needs.setup.outputs.python-version }}
          cache: "pip"
          token: ${{ secrets.GITHUB_TOKEN }}

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip -r requirements-dev.txt
          pip install -e .

      - name: Downgrade git to the Ubuntu official repository's version
        if: ${{ needs.setup.outputs.runner == 'ubuntu-20.04' && needs.setup.outputs.python-version == '3.8' }}
        run: |
          sudo apt update
          sudo apt remove -y git git-man
          sudo add-apt-repository --remove ppa:git-core/ppa
          sudo apt install -y git

      - name: Set up Singularity
        if: ${{ matrix.test == 'test_download.py'}}
        uses: eWaterCycle/setup-singularity@931d4e31109e875b13309ae1d07c70ca8fbc8537 # v7
        with:
          singularity-version: 3.8.3

      - name: Get current date
        id: date
        run: echo "date=$(date +'%Y-%m')" >> $GITHUB_ENV

      - name: Install Nextflow
        uses: nf-core/setup-nextflow@v2

      - name: Install nf-test
        uses: nf-core/setup-nf-test@v1

      - name: move coveragerc file up
        run: |
          mv .github/.coveragerc .

      - name: Test with pytest
        run: |
          python3 -m pytest tests/${{matrix.test}} --color=yes --cov --cov-config=.coveragerc --durations=0 && exit_code=0|| exit_code=$?
          # don't fail if no tests were collected, e.g. for test_licence.py
          if [ "${exit_code}" -eq 5 ]; then
            echo "No tests were collected"
            exit 0
          elif [ "${exit_code}" -ne 0 ]; then
            echo "Tests failed with exit code ${exit_code}"
            exit 1
          fi

      - name: remove slashes from test name
        run: |
          test=$(echo ${{ matrix.test }} | sed 's/\//__/g')
          echo "test=${test}" >> $GITHUB_ENV

      - name: Store snapshot report
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
        if: always()
        with:
          include-hidden-files: true
          name: Snapshot Report ${{ env.test }}
          path: ./snapshot_report.html

      - name: Upload coverage
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
        with:
          include-hidden-files: true
          name: coverage_${{ env.test }}
          path: .coverage

  coverage:
    needs: test
    runs-on:
      - runs-on=${{ github.run_id }}-coverage
      - runner=2cpu-linux-x64
    steps:
      - name: go to subdirectory
        run: |
          mkdir -p pytest
          cd pytest

      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
      - name: Set up Python 3.12
        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
        env:
          AGENT_TOOLSDIRECTORY: /opt/actions-runner/_work/tools/tools/
        with:
          python-version: "3.13"
          cache: "pip"

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip -r requirements-dev.txt
          pip install -e .

      - name: move coveragerc file up
        run: |
          mv .github/.coveragerc .

      - name: Download all artifacts
        uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
      - name: Run coverage
        run: |
          coverage combine --keep coverage*/.coverage*
          coverage report
          coverage xml

      - uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5
        with:
          files: coverage.xml
        env:
          CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
