name: "Check amalgamation"

on:
  pull_request:

permissions:
  contents: read

jobs:
  save:
    runs-on: ubuntu-latest
    steps:
      - name: Harden Runner
        uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
        with:
          egress-policy: audit

      - name: Save PR number
        run: |
          mkdir -p ./pr
          echo ${{ github.event.number }} > ./pr/number
          echo ${{ github.event.pull_request.user.login }} > ./pr/author
      - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
        with:
          name: pr
          path: pr/

  check:
    runs-on: ubuntu-latest
    env:
      MAIN_DIR: ${{ github.workspace }}/main
      INCLUDE_DIR: ${{ github.workspace }}/main/single_include/nlohmann
      TOOL_DIR: ${{ github.workspace }}/tools/tools/amalgamate

    steps:
      - name: Harden Runner
        uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
        with:
          egress-policy: audit

      - name: Checkout pull request
        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          path: main
          ref: ${{ github.event.pull_request.head.sha }}
          persist-credentials: false

      - name: Checkout tools
        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          path: tools
          ref: develop
          persist-credentials: false

      - name: Install astyle
        run: |
          python3 -mvenv venv
          venv/bin/pip3 install -r $MAIN_DIR/tools/astyle/requirements.txt

      - name: Regenerate amalgamation and formatting
        run: |
          cd $MAIN_DIR

          python3 $TOOL_DIR/amalgamate.py -c $TOOL_DIR/config_json.json -s .
          python3 $TOOL_DIR/amalgamate.py -c $TOOL_DIR/config_json_fwd.json -s .

          ${{ github.workspace }}/venv/bin/astyle --project=tools/astyle/.astylerc --suffix=none --quiet \
            $INCLUDE_DIR/json.hpp $INCLUDE_DIR/json_fwd.hpp

          # fail loudly if a directory is renamed or removed: find would only warn
          # about the missing path and silently drop its files from the check
          SOURCE_DIRS="docs/mkdocs/docs/examples include tests"
          for DIR in $SOURCE_DIRS; do
            if [ ! -d "$DIR" ]; then
              echo "::error::source directory '$DIR' does not exist"
              exit 1
            fi
          done

          ${{ github.workspace }}/venv/bin/astyle --project=tools/astyle/.astylerc --suffix=none --quiet \
            $(find $SOURCE_DIRS -type f \( -name '*.hpp' -o -name '*.cpp' -o -name '*.cu' \) -not -path 'tests/thirdparty/*' -not -path 'tests/abi/include/nlohmann/*' | sort)

      - name: Build patch and check for differences
        id: diff
        run: |
          cd $MAIN_DIR
          mkdir -p ${{ github.workspace }}/patch
          git diff --patch --no-color > ${{ github.workspace }}/patch/amalgamation.patch
          if [ -s ${{ github.workspace }}/patch/amalgamation.patch ]; then
            echo "The source code has not been amalgamated/formatted correctly. Diff:"
            cat ${{ github.workspace }}/patch/amalgamation.patch
            echo "has_diff=true" >> "$GITHUB_OUTPUT"
          else
            echo "has_diff=false" >> "$GITHUB_OUTPUT"
          fi

      # Uploaded so contributors can fix their PR with `git apply amalgamation.patch`
      # instead of installing the pinned astyle version locally.
      - name: Upload patch
        if: steps.diff.outputs.has_diff == 'true'
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
        with:
          name: amalgamation-patch
          path: patch/amalgamation.patch

      - name: Fail if not amalgamated/formatted
        if: steps.diff.outputs.has_diff == 'true'
        run: exit 1
