name: Release

on:
  push:
    tags:
      - "v*"

env:
  CARGO_TERM_COLOR: always

jobs:
  build-linux:
    name: Linux x86_64
    runs-on: ubuntu-latest
    permissions:
      contents: write

    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@stable

      - uses: Swatinem/rust-cache@v2

      - name: Install protoc
        uses: arduino/setup-protoc@v3
        with:
          repo-token: ${{ secrets.GITHUB_TOKEN }}

      # fff-search build.rs hard-panics when $CI is set unless the zlob (Zig)
      # feature is enabled. zlob 1.3.3 is currently incompatible with Zig 0.15.2
      # (upstream uses stale std API), so we stick to the pure-Rust globset
      # backend and hide $CI from cargo for this single step.
      - name: Build
        run: env -u CI cargo build --release -p rust-code

      - name: Package
        run: |
          strip target/release/rust-code
          mkdir -p dist/rust-code-linux-x86_64
          cp target/release/rust-code dist/rust-code-linux-x86_64/
          cp README.md dist/rust-code-linux-x86_64/
          cp LICENSE dist/rust-code-linux-x86_64/
          cd dist
          tar czf ../rust-code-linux-x86_64.tar.gz rust-code-linux-x86_64

      - name: Checksums
        run: sha256sum rust-code-linux-x86_64.tar.gz > rust-code-linux-x86_64.tar.gz.sha256

      - name: Upload to release
        uses: softprops/action-gh-release@v2
        with:
          files: |
            rust-code-linux-x86_64.tar.gz
            rust-code-linux-x86_64.tar.gz.sha256

      - name: Output SHA256
        id: sha_linux
        run: echo "sha=$(cat rust-code-linux-x86_64.tar.gz.sha256 | awk '{print $1}')" >> "$GITHUB_OUTPUT"

    outputs:
      sha_linux: ${{ steps.sha_linux.outputs.sha }}

  build-macos:
    name: macOS aarch64
    runs-on: macos-14
    permissions:
      contents: write

    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: aarch64-apple-darwin

      - uses: Swatinem/rust-cache@v2

      - name: Install protoc
        uses: arduino/setup-protoc@v3
        with:
          repo-token: ${{ secrets.GITHUB_TOKEN }}

      # Same fff-search gate workaround as build-linux.
      - name: Build
        run: env -u CI cargo build --release -p rust-code --target aarch64-apple-darwin

      - name: Package
        run: |
          strip target/aarch64-apple-darwin/release/rust-code
          mkdir -p dist/rust-code-macos-aarch64
          cp target/aarch64-apple-darwin/release/rust-code dist/rust-code-macos-aarch64/
          cp README.md dist/rust-code-macos-aarch64/
          cp LICENSE dist/rust-code-macos-aarch64/
          cd dist
          tar czf ../rust-code-macos-aarch64.tar.gz rust-code-macos-aarch64

      - name: Checksums
        run: shasum -a 256 rust-code-macos-aarch64.tar.gz > rust-code-macos-aarch64.tar.gz.sha256

      - name: Upload to release
        uses: softprops/action-gh-release@v2
        with:
          files: |
            rust-code-macos-aarch64.tar.gz
            rust-code-macos-aarch64.tar.gz.sha256

      - name: Output SHA256
        id: sha_macos
        run: echo "sha=$(awk '{print $1}' rust-code-macos-aarch64.tar.gz.sha256)" >> "$GITHUB_OUTPUT"

    outputs:
      sha_macos: ${{ steps.sha_macos.outputs.sha }}

  publish-crate:
    name: Publish to crates.io
    runs-on: ubuntu-latest
    needs: [build-linux]

    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@stable

      - name: Install protoc
        uses: arduino/setup-protoc@v3
        with:
          repo-token: ${{ secrets.GITHUB_TOKEN }}

      - name: Publish rust-code
        # Hide $CI from the fff-search build gate (see build-linux for details).
        run: env -u CI cargo publish -p rust-code --allow-dirty
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}

  update-homebrew:
    name: Update Homebrew formula
    runs-on: ubuntu-latest
    needs: [build-linux, build-macos]
    steps:
      - name: Checkout homebrew-tap
        uses: actions/checkout@v4
        with:
          repository: fortunto2/homebrew-tap
          token: ${{ secrets.HOMEBREW_TAP_TOKEN }}

      - name: Update formula
        env:
          VERSION: ${{ github.ref_name }}
          SHA_LINUX: ${{ needs.build-linux.outputs.sha_linux }}
          SHA_MAC: ${{ needs.build-macos.outputs.sha_macos }}
        run: |
          # Strip 'v' prefix for version
          VER="${VERSION#v}"

          cat > Formula/rust-code.rb << EOF
          class RustCode < Formula
            desc "AI-powered terminal coding agent written in Rust"
            homepage "https://github.com/fortunto2/rust-code"
            version "${VER}"
            license "MIT"

            on_macos do
              on_arm do
                url "https://github.com/fortunto2/rust-code/releases/download/${VERSION}/rust-code-macos-aarch64.tar.gz"
                sha256 "${SHA_MAC}"
              end
            end

            on_linux do
              on_intel do
                url "https://github.com/fortunto2/rust-code/releases/download/${VERSION}/rust-code-linux-x86_64.tar.gz"
                sha256 "${SHA_LINUX}"
              end
            end

            depends_on "tmux"
            depends_on "ripgrep"

            def install
              bin.install "rust-code"
            end

            test do
              assert_match "rust-code", shell_output("#{bin}/rust-code --version")
            end
          end
          EOF

          # Remove leading whitespace from heredoc
          sed -i 's/^          //' Formula/rust-code.rb

      - name: Commit and push
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          git add Formula/rust-code.rb
          git commit -m "Update rust-code to ${VERSION#v}"
          git push
