name: Run nf-test
on:
  push:
    branches:
      - dev
      - master
      - main
    paths-ignore:
      - "docs/**"
      - "**/meta.yml"
      - "**/*.md"
      - "**/*.png"
      - "**/*.svg"
  pull_request:
    paths-ignore:
      - "docs/**"
      - "**/meta.yml"
      - "**/*.md"
      - "**/*.png"
      - "**/*.svg"
  release:
    types: [published]
  workflow_dispatch:

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

env:
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  NFT_VER: "0.9.4"
  NFT_WORKDIR: "~"
  NXF_ANSI_LOG: false
  NXF_SINGULARITY_CACHEDIR: ${{ github.workspace }}/.singularity
  NXF_SINGULARITY_LIBRARYDIR: ${{ github.workspace }}/.singularity

jobs:
  nf-test-changes:
    name: nf-test-changes
    runs-on: # use self-hosted runners
      - runs-on=${{ github.run_id }}-nf-test-changes
      - runner=4cpu-linux-x64
    outputs:
      shard: ${{ steps.set-shards.outputs.shard }}
      total_shards: ${{ steps.set-shards.outputs.total_shards }}
    steps:
      - name: Clean Workspace # Purge the workspace in case it's running on a self-hosted runner
        run: |
          ls -la ./
          rm -rf ./* || true
          rm -rf ./.??* || true
          ls -la ./
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
        with:
          fetch-depth: 0

      - name: get number of shards
        id: set-shards
        uses: ./.github/actions/get-shards
        env:
          NFT_VER: ${{ env.NFT_VER }}
        with:
          max_shards: 25
          tags: modules_local,subworkflows_local,pipeline

      - name: debug
        run: |
          echo ${{ steps.set-shards.outputs.shard }}
          echo ${{ steps.set-shards.outputs.total_shards }}

  nf-test:
    name: "${{ matrix.profile }} | ${{ matrix.NXF_VER }} | ${{ matrix.shard }}/${{ needs.nf-test-changes.outputs.total_shards }}"
    needs: [nf-test-changes]
    if: ${{ needs.nf-test-changes.outputs.total_shards != '0' }}
    runs-on: # use self-hosted runners
      - runs-on=${{ github.run_id }}-nf-test
      - runner=4cpu-linux-x64
      - volume=100gb
    strategy:
      fail-fast: false
      matrix:
        shard: ${{ fromJson(needs.nf-test-changes.outputs.shard) }}
        profile: [conda, docker, singularity]
        isMain:
          - ${{ github.base_ref == 'master' || github.base_ref == 'main' }}
        # Exclude conda and singularity on dev
        exclude:
          - isMain: false
            profile: "conda"
          - isMain: false
            profile: "singularity"
        NXF_VER:
          - "25.10.4"
          - "latest-everything"
    env:
      NXF_ANSI_LOG: false
      TOTAL_SHARDS: ${{ needs.nf-test-changes.outputs.total_shards }}

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
        with:
          fetch-depth: 0

      - name: Run nf-test
        id: run_nf_test
        uses: ./.github/actions/nf-test
        continue-on-error: ${{ matrix.NXF_VER == 'latest-everything' }}
        env:
          NFT_WORKDIR: ${{ env.NFT_WORKDIR }}
          NXF_VERSION: ${{ matrix.NXF_VER }}
        with:
          profile: ${{ matrix.profile }}
          shard: ${{ matrix.shard }}
          total_shards: ${{ env.TOTAL_SHARDS }}

      - name: Report test status
        if: ${{ always() }}
        run: |
          if [[ "${{ steps.run_nf_test.outcome }}" == "failure" ]]; then
            echo "::error::Test with ${{ matrix.NXF_VER }} failed"
            # Add to workflow summary
            echo "## ❌ Test failed: ${{ matrix.profile }} | ${{ matrix.NXF_VER }} | Shard ${{ matrix.shard }}/${{ env.TOTAL_SHARDS }}" >> $GITHUB_STEP_SUMMARY
            if [[ "${{ matrix.NXF_VER }}" == "latest-everything" ]]; then
              echo "::warning::Test with latest-everything failed but will not cause workflow failure. Please check if the error is expected or if it needs fixing."
            fi
            if [[ "${{ matrix.NXF_VER }}" != "latest-everything" ]]; then
              exit 1
            fi
          fi

      # continue-on-error keeps latest-everything from failing the job, so it never shows up in
      # `needs.nf-test.result` downstream and CI stays green. Surface it via a PR comment instead;
      # other NXF_VER failures already fail the job/CI directly, so no comment is needed for those.
      - name: Prepare PR comment fragment
        if: ${{ always() && steps.run_nf_test.outcome == 'failure' && matrix.NXF_VER == 'latest-everything' }}
        run: |
          mkdir -p pr-comment-fragment
          echo "* ❌ \`${{ matrix.profile }}\` | \`${{ matrix.NXF_VER }}\` | Shard ${{ matrix.shard }}/${{ env.TOTAL_SHARDS }}" > pr-comment-fragment/fragment.md

      - name: Upload PR comment fragment
        if: ${{ always() && steps.run_nf_test.outcome == 'failure' && matrix.NXF_VER == 'latest-everything' }}
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
        with:
          name: pr-comment-fragment-${{ strategy.job-index }}
          path: pr-comment-fragment/

  confirm-pass:
    needs: nf-test
    if: always()
    runs-on: # use self-hosted runners
      - runs-on=${{ github.run_id }}-confirm-pass
      - runner=2cpu-linux-x64
    steps:
      - name: One or more tests failed (excluding latest-everything)
        if: ${{ contains(needs.*.result, 'failure') }}
        run: exit 1

      - name: One or more tests cancelled
        if: ${{ contains(needs.*.result, 'cancelled') }}
        run: exit 1

      - name: All tests ok
        if: ${{ contains(needs.*.result, 'success') }}
        run: exit 0

      - name: debug-print
        if: always()
        run: |
          echo "::group::DEBUG: `needs` Contents"
          echo "DEBUG: toJSON(needs) = ${{ toJSON(needs) }}"
          echo "DEBUG: toJSON(needs.*.result) = ${{ toJSON(needs.*.result) }}"
          echo "::endgroup::"

      - name: Download PR comment fragments
        if: ${{ always() }}
        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
        continue-on-error: true
        with:
          pattern: pr-comment-fragment-*
          path: pr-comment-fragments
          merge-multiple: true

      # Build a comment for the shared pr-comment.yml poster to publish on the PR.
      # Based on the fragments above (not needs.*.result) so non-blocking failures are still reported.
      - name: Prepare PR comment
        if: ${{ always() }}
        env:
          PR_NUMBER: ${{ github.event.pull_request.number }}
          RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
        run: |
          mkdir -p pr-comment
          echo "$PR_NUMBER" > pr-comment/pr_number.txt
          echo "nf-test" > pr-comment/header.txt
          if [ -d pr-comment-fragments ] && [ -n "$(ls -A pr-comment-fragments)" ]; then
            {
              echo "## ❌ nf-test failed with latest Nextflow version"
              echo ""
              echo "> [!NOTE]"
              echo "> Tests with Nextflow's latest version failed but it will not cause a CI workflow failure."
              echo "> Please check if the failure is expected with newer (edge-)releases of Nextflow or if it needs fixing."
              echo ""
              cat pr-comment-fragments/*.md
              echo ""
              echo "See the [full run](${RUN_URL}) for details."
            } > pr-comment/comment.md
          fi

      - name: Upload PR comment artifact
        if: ${{ always() }}
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
        with:
          name: pr-comment
          path: pr-comment/
