name: Test Example on PR
on:
  pull_request:
    branches:
      - "main"
      - "develop"
      - "feature/**"
    # any change in the examples folder will trigger check for the corresponding example.
    paths:
      - "examples/**"

jobs:
  # This is for changed example files detect and output a matrix containing all the corresponding directory name.
  detect-changed-example:
    if: |
      github.event.pull_request.draft == false &&
      github.event.pull_request.base.repo.full_name == 'hpcaitech/ColossalAI' && github.event_name == 'pull_request'
    runs-on: ubuntu-latest
    outputs:
      matrix: ${{ steps.setup-matrix.outputs.matrix }}
      anyChanged: ${{ steps.setup-matrix.outputs.anyChanged }}
    name: Detect changed example files
    concurrency:
      group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}-detect-change
      cancel-in-progress: true
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0
          ref: ${{ github.event.pull_request.head.sha }}

      - name: Locate base commit
        id: locate-base-sha
        run: |
          curBranch=$(git rev-parse --abbrev-ref HEAD)
          commonCommit=$(git merge-base origin/main $curBranch)
          echo $commonCommit
          echo "baseSHA=$commonCommit" >> $GITHUB_OUTPUT

      - name: Get all changed example files
        id: changed-files
        uses: tj-actions/changed-files@v35
        with:
          base_sha: ${{ steps.locate-base-sha.outputs.baseSHA }}

      - name: setup matrix
        id: setup-matrix
        run: |
          changedFileName=""
          for file in ${{ steps.changed-files.outputs.all_changed_files  }}; do
            changedFileName="${file}:${changedFileName}"
          done
          echo "$changedFileName was changed"
          res=`python .github/workflows/scripts/example_checks/detect_changed_example.py --fileNameList $changedFileName`
          echo "All changed examples are $res"

          if [ "$res" == "[]" ]; then
            echo "anyChanged=false" >> $GITHUB_OUTPUT
            echo "matrix=null" >> $GITHUB_OUTPUT
          else
            dirs=$( IFS=',' ; echo "${res[*]}" )
            echo "anyChanged=true" >> $GITHUB_OUTPUT
            echo "matrix={\"directory\":$(echo "$dirs")}" >> $GITHUB_OUTPUT
          fi

  # If no file is changed, it will prompt an error and shows the matrix do not have value.
  check-changed-example:
    # Add this condition to avoid executing this job if the trigger event is workflow_dispatch.
    if: |
      github.event.pull_request.draft == false &&
      github.event.pull_request.base.repo.full_name == 'hpcaitech/ColossalAI' && github.event_name == 'pull_request' &&
      needs.detect-changed-example.outputs.anyChanged == 'true'
    name: Test the changed example
    needs: detect-changed-example
    runs-on: [self-hosted, gpu]
    strategy:
      fail-fast: false
      matrix: ${{fromJson(needs.detect-changed-example.outputs.matrix)}}
    container:
      image: hpcaitech/pytorch-cuda:2.1.0-12.1.0
      options: --gpus all --rm -v /data/scratch/examples-data:/data/
    timeout-minutes: 20
    concurrency:
      group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}-run-example-${{ matrix.directory }}
      cancel-in-progress: true
    steps:
      - uses: actions/checkout@v3

      - name: Install Colossal-AI
        run: |
          CUDA_EXT=1 pip install -v .

      - name: Test the example
        run: |
          example_dir=${{ matrix.directory }}
          cd "${PWD}/examples/${example_dir}"
          bash test_ci.sh
        env:
          NCCL_SHM_DISABLE: 1
