name: test

on: push
permissions:
  contents: write
  actions: write

jobs:

  test:
    runs-on: ubuntu-latest
    if: github.ref_name == 'dev'
    defaults:
      run:
        shell: bash -l {0}

    steps:
      - name: Delete cache to save space
        # https://github.com/orgs/community/discussions/25678#discussioncomment-5242449
        run: rm -rf /opt/hostedtoolcache

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

      - uses: chetan/git-restore-mtime-action@v2

      - uses: conda-incubator/setup-miniconda@v3
        with:
          python-version: "3.12"
          auto-update-conda: true
          activate-environment: immunopipe
          channels: conda-forge,defaults

      - name: Change conda envs permissions
        # https://github.com/actions/cache/issues/133
        run: |
          sudo chown -R $USER $CONDA/envs
          sudo chmod -R 0777 $CONDA/envs

      - name: Restore conda environment
        id: restore-conda
        uses: actions/cache/restore@v5
        with:
          path: ${{ env.CONDA }}/envs/immunopipe
          key: conda-${{ hashFiles('docker/environment_base.yml') }}-${{ hashFiles('docker/environment_rpkgs.yml') }}-${{ env.CACHE_NUMBER }}
        env:
          TAR_OPTIONS: "--no-same-owner --no-same-permissions"
          CACHE_NUMBER: 1

      - name: Create conda environment (if not restored)
        if: steps.restore-conda.outputs.cache-hit != 'true'
        run: |
          conda env create -y -f docker/environment_base.yml --name immunopipe
          conda activate immunopipe
          conda env update -f docker/environment_rpkgs.yml --name immunopipe

      - name: Cache conda environment
        id: cache-conda
        if: steps.restore-conda.outputs.cache-hit != 'true'
        uses: actions/cache/save@v5
        with:
          path: ${{ env.CONDA }}/envs/immunopipe
          key: ${{ steps.restore-conda.outputs.cache-primary-key }}

      - name: List conda information
        run: |
          conda info
          conda list
          conda config --show-sources
          conda config --show

      - name: Install immunopipe
        run: |
          # For tests
          uv pip install --system pytest pytest-forked pytest-asyncio pytest-order pytest-cov pipen-dry
          uv pip install --system -e ".[cli-gbatch]"

      - name: Check if some packages can be imported
        run: |
          echo "Checking scanpy ..."
          python -c "import scanpy, importlib.metadata; print(f'scanpy version: {importlib.metadata.version('scanpy')}')"
          echo "Checking liana ..."
          python -c "import liana, importlib.metadata; print(f'liana version: {importlib.metadata.version('liana')}')"
          echo "Checking celltypist2 ..."
          python -c "import celltypist, importlib.metadata; print(f'celltypist2 version: {importlib.metadata.version('celltypist2')}')"
          echo "Checking BioPython ..."
          python -c "import Bio, importlib.metadata; print(f'BioPython version: {importlib.metadata.version('BioPython')}')"
          echo "Checking keras ..."
          python -c "import keras, importlib.metadata; print(f'keras version: {importlib.metadata.version('keras')}')"
          echo "Checking tensorflow ..."
          python -c "import tensorflow, importlib.metadata; print(f'tensorflow version: {importlib.metadata.version('tensorflow')}')"
          echo "Checking umap-learn ..."
          python -c "import umap, importlib.metadata; print(f'umap-learn version: {importlib.metadata.version('umap-learn')}')"
          echo "Checking stringfish (R) ..."
          R -e "library(stringfish); packageVersion('stringfish')"

      - name: Check if immunopipe is installed successfully
        run: |
          if ! immunopipe >/dev/null; then
            echo "immunopipe is not installed successfully"
            # print the error
            immunopipe
            exit 1
          else # test if the TEST_STRING is in the help message
            if ! immunopipe | grep -q "$TEST_STRING"; then
              echo "immunopipe is not installed successfully"
              # print the error
              immunopipe
              exit 1
            fi
          fi
        env:
          TEST_STRING: "Integrative analysis for scRNA-seq and scTCR-/scBCR-seq data"

      - name: Restore running data
        id: restore-running
        uses: actions/cache/restore@v5
        with:
          path: tests/running/
          key: tests-running-${{ env.CACHE_NUMBER }}
        env:
          TAR_OPTIONS: "--no-same-owner --no-same-permissions --skip-old-files"
          ACTIONS_CACHE_SERVICE_V2: true
          CACHE_NUMBER: 1

      - name: Download input data (if not restored)
        if: steps.restore-running.outputs.cache-hit != 'true'
        run: make test-data

      - name: Run tests
        run: pytest tests -v

      - name: Add README.md to tests/running/output
        run: |
          echo "# Tests output for immunopipe" > $OUTPUT_DIR/README.md
          echo "" >> $OUTPUT_DIR/README.md
          echo "This directory contains the output of the tests for immunopipe" >> $OUTPUT_DIR/README.md
          echo "" >> $OUTPUT_DIR/README.md
          echo "The output can be used for documentation purposes" >> $OUTPUT_DIR/README.md
        env:
          OUTPUT_DIR: tests/running/output

      - name: Create .gitignore for tests/running/output
        run: |
          echo "**/*.RDS" > $OUTPUT_DIR/.gitignore
          echo "**/*.rds" >> $OUTPUT_DIR/.gitignore
          echo "**/*.qs" >> $OUTPUT_DIR/.gitignore
          echo "**/*.qs2" >> $OUTPUT_DIR/.gitignore
          echo "**/*.json" >> $OUTPUT_DIR/.gitignore
          echo "**/*.txt" >> $OUTPUT_DIR/.gitignore
          echo "**/*.tsv" >> $OUTPUT_DIR/.gitignore
          echo "**/*.pdf" >> $OUTPUT_DIR/.gitignore
        env:
          OUTPUT_DIR: tests/running/output

      - name: Deploy output to tests-output branch
        uses: JamesIves/github-pages-deploy-action@v4
        with:
          folder: tests/running/output
          branch: tests-output
          token: ${{ secrets.GITHUB_TOKEN }}
          force: true

      - name: Delete old test running data cache
        continue-on-error: true
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        # if: steps.restore-running.outputs.cache-hit != 'true'
        # Using `--repo` makes it so that this step doesn't require checking out the
        # repo first.
        run: gh cache delete --repo ${{ github.repository }} ${{ steps.restore-running.outputs.cache-primary-key }}

      - name: Cache running data
        id: cache-running
        if: always()
        uses: actions/cache/save@v5
        with:
          path: tests/running/
          key: ${{ steps.restore-running.outputs.cache-primary-key }}
        env:
          ACTIONS_CACHE_SERVICE_V2: true

  build:
    needs: [test]
    if: |
      always()
      && !contains(needs.*.result, 'failure')
      && !contains(needs.*.result, 'cancelled')
    uses: ./.github/workflows/build.yml
    secrets: inherit
