name: diff-shades

on:
  push:
    branches: [main]
    paths: ["src/**", "pyproject.toml", ".github/workflows/*"]

  pull_request:
    paths: ["src/**", "pyproject.toml", ".github/workflows/*"]

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
  cancel-in-progress: true

jobs:
  configure:
    runs-on: ubuntu-latest
    outputs:
      matrix: ${{ steps.set-config.outputs.matrix }}

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v4
        with:
          python-version: "*"

      - name: Install diff-shades and support dependencies
        run: |
          python -m pip install 'click==8.1.3' packaging urllib3
          python -m pip install https://github.com/ichard26/diff-shades/archive/stable.zip

      - name: Calculate run configuration & metadata
        id: set-config
        env:
          GITHUB_TOKEN: ${{ github.token }}
        run: >
          python scripts/diff_shades_gha_helper.py config ${{ github.event_name }} ${{ matrix.mode }}

  analysis:
    name: analysis / ${{ matrix.mode }}
    needs: configure
    runs-on: ubuntu-latest
    env:
      HATCH_BUILD_HOOKS_ENABLE: "1"
      # Clang is less picky with the C code it's given than gcc (and may
      # generate faster binaries too).
      CC: clang-14
    strategy:
      fail-fast: false
      matrix:
        include: ${{ fromJson(needs.configure.outputs.matrix )}}

    steps:
      - name: Checkout this repository (full clone)
        uses: actions/checkout@v4
        with:
          # The baseline revision could be rather old so a full clone is ideal.
          fetch-depth: 0

      - uses: actions/setup-python@v4
        with:
          python-version: "*"

      - name: Install diff-shades and support dependencies
        run: |
          python -m pip install https://github.com/ichard26/diff-shades/archive/stable.zip
          python -m pip install 'click==8.1.3' packaging urllib3
          # After checking out old revisions, this might not exist so we'll use a copy.
          cat scripts/diff_shades_gha_helper.py > helper.py
          git config user.name "diff-shades-gha"
          git config user.email "diff-shades-gha@example.com"

      - name: Attempt to use cached baseline analysis
        id: baseline-cache
        uses: actions/cache@v3
        with:
          path: ${{ matrix.baseline-analysis }}
          key: ${{ matrix.baseline-cache-key }}

      - name: Build and install baseline revision
        if: steps.baseline-cache.outputs.cache-hit != 'true'
        env:
          GITHUB_TOKEN: ${{ github.token }}
        run: >
          ${{ matrix.baseline-setup-cmd }}
          && python -m pip install .

      - name: Analyze baseline revision
        if: steps.baseline-cache.outputs.cache-hit != 'true'
        run: >
          diff-shades analyze -v --work-dir projects-cache/
          ${{ matrix.baseline-analysis }} ${{ matrix.force-flag }}

      - name: Build and install target revision
        env:
          GITHUB_TOKEN: ${{ github.token }}
        run: >
          ${{ matrix.target-setup-cmd }}
          && python -m pip install .

      - name: Analyze target revision
        run: >
          diff-shades analyze -v --work-dir projects-cache/
          ${{ matrix.target-analysis }} --repeat-projects-from
          ${{ matrix.baseline-analysis }} ${{ matrix.force-flag }}

      - name: Generate HTML diff report
        run: >
          diff-shades --dump-html diff.html compare --diff
          ${{ matrix.baseline-analysis }} ${{ matrix.target-analysis }}

      - name: Upload diff report
        uses: actions/upload-artifact@v3
        with:
          name: ${{ matrix.mode }}-diff.html
          path: diff.html

      - name: Upload baseline analysis
        uses: actions/upload-artifact@v3
        with:
          name: ${{ matrix.baseline-analysis }}
          path: ${{ matrix.baseline-analysis }}

      - name: Upload target analysis
        uses: actions/upload-artifact@v3
        with:
          name: ${{ matrix.target-analysis }}
          path: ${{ matrix.target-analysis }}

      - name: Generate summary file (PR only)
        if: github.event_name == 'pull_request' && matrix.mode == 'preview-changes'
        run: >
          python helper.py comment-body
          ${{ matrix.baseline-analysis }} ${{ matrix.target-analysis }}
          ${{ matrix.baseline-sha }} ${{ matrix.target-sha }}
          ${{ github.event.pull_request.number }}

      - name: Upload summary file (PR only)
        if: github.event_name == 'pull_request' && matrix.mode == 'preview-changes'
        uses: actions/upload-artifact@v3
        with:
          name: .pr-comment.json
          path: .pr-comment.json

      - name: Verify zero changes (PR only)
        if: matrix.mode == 'assert-no-changes'
        run: >
          diff-shades compare --check ${{ matrix.baseline-analysis }} ${{ matrix.target-analysis }}
          || (echo "Please verify you didn't change the stable code style unintentionally!" && exit 1)

      - name: Check for failed files for target revision
        # Even if the previous step failed, we should still check for failed files.
        if: always()
        run: >
          diff-shades show-failed --check --show-log ${{ matrix.target-analysis }}
