name: Release Binaries

on:
  push:
    tags: ['v*']

jobs:
  build:
    name: Build (${{ matrix.target }})
    strategy:
      fail-fast: true
      matrix:
        include:
          - target: x86_64-unknown-linux-gnu
            os: ubuntu-22.04
            archive: tar.gz
          - target: aarch64-unknown-linux-gnu
            os: ubuntu-22.04-arm
            archive: tar.gz
          - target: x86_64-apple-darwin
            os: macos-14            # ARM runner cross-compiles to x64 (macos-13 deprecated)
            archive: tar.gz
          - target: aarch64-apple-darwin
            os: macos-14
            archive: tar.gz
          - target: x86_64-pc-windows-msvc
            os: windows-latest
            archive: zip
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@1.85
      - name: Add cross-compile target
        run: rustup target add ${{ matrix.target }}
      - uses: Swatinem/rust-cache@v2
        with:
          key: ${{ matrix.target }}
      - run: cargo build --release --target ${{ matrix.target }}
      - name: Package (Unix)
        if: matrix.archive == 'tar.gz'
        shell: bash
        run: |
          cd target/${{ matrix.target }}/release
          tar czf ../../../precommit-verify-${{ matrix.target }}.tar.gz precommit-verify
      - name: Package (Windows)
        if: matrix.archive == 'zip'
        shell: pwsh
        run: |
          Compress-Archive -Path target\${{ matrix.target }}\release\precommit-verify.exe `
            -DestinationPath precommit-verify-${{ matrix.target }}.zip
      - uses: actions/upload-artifact@v4
        with:
          name: binary-${{ matrix.target }}
          path: precommit-verify-${{ matrix.target }}.*
          retention-days: 1

  github-release:
    name: Attach binaries to GitHub Release
    needs: build
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - uses: actions/download-artifact@v4
        with:
          pattern: binary-*
          merge-multiple: true
      - uses: softprops/action-gh-release@v2
        with:
          files: |
            precommit-verify-*.tar.gz
            precommit-verify-*.zip
          fail_on_unmatched_files: true
          # body / body_path is intentionally omitted so the release notes
          # generated by release-plz remain untouched.

  npm-publish:
    name: Publish npm package
    needs: build
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '22'
          registry-url: 'https://registry.npmjs.org'
      - uses: actions/download-artifact@v4
        with:
          pattern: binary-*
          merge-multiple: true
          path: artifacts
      - name: Extract binaries into npm/binaries/
        shell: bash
        run: |
          mkdir -p npm/binaries
          for target in x86_64-unknown-linux-gnu aarch64-unknown-linux-gnu \
                        x86_64-apple-darwin aarch64-apple-darwin; do
            tar -xzf "artifacts/precommit-verify-${target}.tar.gz" -C npm/binaries
            mv npm/binaries/precommit-verify "npm/binaries/precommit-verify-${target}"
            chmod +x "npm/binaries/precommit-verify-${target}"
          done
          unzip "artifacts/precommit-verify-x86_64-pc-windows-msvc.zip" -d npm/binaries
          mv npm/binaries/precommit-verify.exe \
             npm/binaries/precommit-verify-x86_64-pc-windows-msvc.exe
      - name: Sync version from git tag to package.json
        shell: bash
        run: |
          VERSION="${GITHUB_REF_NAME#v}"
          cd npm
          npm version --no-git-tag-version "$VERSION"
      - name: Smoke test launcher
        shell: bash
        run: |
          node npm/lib/index.js --help
          set +e
          OUTPUT=$(PRECOMMIT_VERIFY_FORCE_PLATFORM='aix-x64' node npm/lib/index.js --help 2>&1)
          EXIT=$?
          set -e
          test "$EXIT" -eq 1 || (echo "expected exit 1 for unsupported platform, got $EXIT" && exit 1)
          echo "$OUTPUT" | grep -q 'unsupported platform' \
            || (echo "expected error message containing 'unsupported platform', got: $OUTPUT" && exit 1)
      - name: Publish to npm
        run: npm publish --provenance --access public
        working-directory: npm
        env:
          # Phase 2-A: token-based publish. Remove this env after enabling
          # npm trusted publishing (Phase 2-C) to switch to OIDC.
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

  verify-publish:
    name: Verify published package (${{ matrix.os }})
    needs: npm-publish
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, ubuntu-22.04-arm, macos-14, windows-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/setup-node@v4
        with:
          node-version: '22'
      - name: Install and run published package
        shell: bash
        run: |
          VERSION="${GITHUB_REF_NAME#v}"
          for i in 1 2 3; do
            if npx -y "precommit-verify@${VERSION}" --help; then exit 0; fi
            sleep 10
          done
          exit 1
