panoptico 1.1.1

AI-powered code review CLI for Pull Requests using Claude
Documentation
name: Release

on:
  push:
    tags:
      - 'v*.*.*'

env:
  CARGO_TERM_COLOR: always
  RUSTFLAGS: -D warnings

permissions:
  contents: write

jobs:
  verify-version:
    name: Verify tag matches Cargo.toml
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.extract.outputs.version }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Extract version from tag
        id: extract
        run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"

      - name: Compare with Cargo.toml
        run: |
          cargo_version=$(grep -m1 '^version' Cargo.toml | sed -E 's/.*"([^"]+)".*/\1/')
          tag_version="${{ steps.extract.outputs.version }}"
          if [ "$cargo_version" != "$tag_version" ]; then
            echo "::error::Cargo.toml version ($cargo_version) does not match tag ($tag_version)"
            exit 1
          fi
          echo "Version match: $tag_version"

  build:
    name: Build ${{ matrix.target }}
    needs: verify-version
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            archive: tar.gz
            binary: panoptico
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            archive: zip
            binary: panoptico.exe

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}

      - name: Cache cargo
        uses: Swatinem/rust-cache@v2
        with:
          key: ${{ matrix.target }}

      - name: Build release
        run: cargo build --release --target ${{ matrix.target }} --locked

      - name: Package archive (Linux)
        if: matrix.archive == 'tar.gz'
        shell: bash
        run: |
          set -euo pipefail
          name="panoptico-${GITHUB_REF_NAME}-${{ matrix.target }}"
          mkdir -p "dist/$name"
          cp "target/${{ matrix.target }}/release/${{ matrix.binary }}" "dist/$name/"
          cp README.md LICENSE-MIT LICENSE-APACHE "dist/$name/"
          tar -C dist -czf "dist/$name.tar.gz" "$name"
          ( cd dist && sha256sum "$name.tar.gz" > "$name.tar.gz.sha256" )

      - name: Package archive (Windows)
        if: matrix.archive == 'zip'
        shell: pwsh
        run: |
          $name = "panoptico-$env:GITHUB_REF_NAME-${{ matrix.target }}"
          New-Item -ItemType Directory -Path "dist\$name" -Force | Out-Null
          Copy-Item "target\${{ matrix.target }}\release\${{ matrix.binary }}" "dist\$name\"
          Copy-Item README.md, LICENSE-MIT, LICENSE-APACHE "dist\$name\"
          Compress-Archive -Path "dist\$name" -DestinationPath "dist\$name.zip"
          $hash = (Get-FileHash "dist\$name.zip" -Algorithm SHA256).Hash.ToLower()
          "$hash  $name.zip" | Out-File -Encoding ascii "dist\$name.zip.sha256"

      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: release-${{ matrix.target }}
          path: |
            dist/*.tar.gz
            dist/*.zip
            dist/*.sha256
          if-no-files-found: error

  release:
    name: Publish GitHub Release
    needs: [verify-version, build]
    runs-on: ubuntu-latest
    steps:
      - name: Download all artifacts
        uses: actions/download-artifact@v4
        with:
          path: artifacts
          merge-multiple: true

      - name: List release assets
        run: ls -la artifacts/

      - name: Create release
        uses: softprops/action-gh-release@v2
        with:
          tag_name: ${{ github.ref_name }}
          name: panoptico ${{ needs.verify-version.outputs.version }}
          generate_release_notes: true
          fail_on_unmatched_files: true
          files: |
            artifacts/*.tar.gz
            artifacts/*.zip
            artifacts/*.sha256

  publish-crate:
    name: Publish to crates.io
    needs: [verify-version, release]
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@stable

      - name: Cache cargo
        uses: Swatinem/rust-cache@v2

      - name: Check if version already on crates.io
        id: check
        run: |
          set -euo pipefail
          version="${{ needs.verify-version.outputs.version }}"
          if curl -fsSLo /dev/null "https://crates.io/api/v1/crates/panoptico/$version"; then
            echo "exists=true" >> "$GITHUB_OUTPUT"
            echo "Version $version already published to crates.io, skipping publish step"
          else
            echo "exists=false" >> "$GITHUB_OUTPUT"
          fi

      - name: Verify package
        if: steps.check.outputs.exists == 'false'
        run: cargo package --locked

      - name: Publish to crates.io
        if: steps.check.outputs.exists == 'false'
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
        run: cargo publish --locked