name: Sync Homebrew formula

# On every version tag, recompute the release tarball checksum and push an
# updated Formula/yellowjacket.rb into the Homebrew tap repo. Keeping the tap
# in a separate repo (github.com/Shadow-Puppet/homebrew-yellowjacket) is what
# lets users install with a single command:
#
#   brew install shadow-puppet/yellowjacket/yellowjacket
#
# (`shadow-puppet/yellowjacket` is shorthand for the homebrew-yellowjacket repo;
# brew auto-taps it, so no separate `brew tap` step is needed.)

on:
  push:
    tags:
      - "v*"
  workflow_dispatch:
    inputs:
      version:
        description: "Version to sync (default: the pushed tag)"
        required: false

concurrency:
  group: homebrew-${{ github.ref }}
  cancel-in-progress: true

jobs:
  sync-formula:
    runs-on: ubuntu-latest
    env:
      # GitHub PAT (or fine-grained token) with write access to the tap repo.
      TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
      # Gitea source that serves the release tarball referenced by the formula.
      SOURCE_TARBALL_BASE: https://git.ljones.me/yonlu/yellowjacket/archive
      # separate GitHub tap repo the formula is published to.
      TAP_REPO: Shadow-Puppet/homebrew-yellowjacket
    steps:
      - name: Check out source (for the canonical formula)
        uses: actions/checkout@v4

      - name: Compute version and tarball checksum
        id: version
        run: |
          set -euo pipefail
          TAG="${{ inputs.version }}"
          [ -n "$TAG" ] || TAG="${GITHUB_REF_NAME}"   # e.g. v0.0.1
          case "$TAG" in v*) ;; *) TAG="v$TAG" ;; esac
          VERSION="${TAG#v}"                          # e.g. 0.0.1

          # v0.0.0 is semantic-release's version floor, not a shipment —
          # see the bootstrap step in release.yml.  Skipped cleanly rather
          # than failing: this one would otherwise push a formula for a
          # version that does not exist into a *public* tap.
          if [ "$VERSION" = "0.0.0" ]; then
            echo "v0.0.0 is the version floor, not a release; nothing to sync"
            echo "skip=true" >> "$GITHUB_OUTPUT"
            exit 0
          fi

          # Nor is a prerelease, and this trigger is `v*`, which matches
          # `v0.4.0-beta.1`.  It matters most here of the four: the tap
          # is public, and `brew upgrade` would offer a beta to everyone
          # on it.
          case "$VERSION" in
            *-*)
              echo "$TAG is a prerelease; not syncing it to a public tap"
              echo "skip=true" >> "$GITHUB_OUTPUT"
              exit 0
              ;;
          esac
          echo "skip=false" >> "$GITHUB_OUTPUT"

          TARBALL="${SOURCE_TARBALL_BASE}/${TAG}.tar.gz"

          echo "Fetching ${TARBALL}"
          # Retry briefly: the tag archive can lag a few seconds behind the push.
          for attempt in 1 2 3 4 5; do
            if curl -fSsL "$TARBALL" -o release.tar.gz; then
              break
            fi
            echo "attempt ${attempt} failed, retrying..."
            sleep 5
          done

          SHA256="$(sha256sum release.tar.gz | cut -d' ' -f1)"
          echo "version=${VERSION} sha256=${SHA256}"

          echo "VERSION=${VERSION}" >> "$GITHUB_ENV"
          echo "SHA256=${SHA256}"   >> "$GITHUB_ENV"

      - name: Render the formula with the new version and checksum
        if: steps.version.outputs.skip == 'false'
        run: |
          set -euo pipefail
          src="packaging/homebrew/Formula/yellowjacket.rb"
          # Rewrite only the two managed lines; the interpolated url picks up the
          # new version automatically.
          sed -E \
            -e "s|^  version \".*\"|  version \"${VERSION}\"|" \
            -e "s|^  sha256 \".*\"|  sha256 \"${SHA256}\"|" \
            "$src" > yellowjacket.rb
          echo "----- rendered formula -----"
          cat yellowjacket.rb

      - name: Push to the Homebrew tap repo
        if: steps.version.outputs.skip == 'false'
        run: |
          set -euo pipefail
          git clone "https://x-access-token:${TAP_TOKEN}@github.com/${TAP_REPO}.git" tap
          mkdir -p tap/Formula
          cp yellowjacket.rb tap/Formula/yellowjacket.rb

          cd tap
          git config user.name  "yellowjacket-ci"
          git config user.email "yj@yellowjacket.app"

          if git diff --quiet; then
            echo "Formula already up to date; nothing to push."
            exit 0
          fi

          git add Formula/yellowjacket.rb
          git commit -m "yellowjacket ${VERSION}"
          git push origin HEAD:main
