fledge 1.3.0

Dev lifecycle CLI. One tool for the dev loop, any language.
name: Post-Release Formula Update

# Runs after the Release workflow finishes uploading binaries + their .sha256
# sidecars. Pulls the real shas, rewrites the formula in CorvidLabs/homebrew-tap
# with the new version + shas. This is the only correct moment to bump the
# formula — at `fledge release` time the new version's binaries don't exist
# yet, so any pre-build sha would be a lie.
#
# Security note: every value derived from `github.event.workflow_run.*` (or
# any other potentially attacker-controlled context) flows through an `env:`
# block before reaching a shell. Direct `${{ … }}` interpolation inside
# `run: |` is a code-injection sink and is intentionally avoided here.

permissions:
  contents: read

on:
  workflow_run:
    workflows: ["Release"]
    types: [completed]

jobs:
  update-formula:
    if: ${{ github.event.workflow_run.conclusion == 'success' && startsWith(github.event.workflow_run.head_branch, 'v') }}
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          ref: main

      - name: Resolve release tag
        id: tag
        env:
          HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }}
        run: |
          set -euo pipefail
          if ! [[ "$HEAD_BRANCH" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([-+][0-9A-Za-z.-]+)?$ ]]; then
            echo "::error::Refusing to run with non-semver tag '$HEAD_BRANCH'"
            exit 1
          fi
          {
            echo "tag=$HEAD_BRANCH"
            echo "version=${HEAD_BRANCH#v}"
          } >> "$GITHUB_OUTPUT"

      - name: Fetch sha256 sidecars from release
        id: shas
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          TAG: ${{ steps.tag.outputs.tag }}
          REPO: ${{ github.repository }}
        run: |
          set -euo pipefail
          fetch() {
            gh release download "$TAG" -p "$1.sha256" -R "$REPO" -O - \
              | awk '{print $1}'
          }
          validate() {
            local sha="$1"
            if ! [[ "$sha" =~ ^[0-9a-fA-F]{64}$ ]]; then
              echo "::error::Invalid sha256 from sidecar: '$sha'"
              exit 1
            fi
            printf '%s' "$sha"
          }
          {
            echo "macos_aarch64=$(validate "$(fetch fledge-macos-aarch64)")"
            echo "macos_x86_64=$(validate "$(fetch fledge-macos-x86_64)")"
            echo "linux_x86_64=$(validate "$(fetch fledge-linux-x86_64)")"
          } >> "$GITHUB_OUTPUT"

      - name: Sync formula to homebrew-tap
        env:
          GH_TOKEN: ${{ secrets.TAP_GITHUB_TOKEN }}
          NEW_VERSION: ${{ steps.tag.outputs.version }}
          MACOS_AARCH64: ${{ steps.shas.outputs.macos_aarch64 }}
          MACOS_X86_64: ${{ steps.shas.outputs.macos_x86_64 }}
          LINUX_X86_64: ${{ steps.shas.outputs.linux_x86_64 }}
        run: |
          set -euo pipefail
          if [ -z "$GH_TOKEN" ]; then
            echo "::error::TAP_GITHUB_TOKEN secret is required"
            exit 1
          fi
          git clone "https://x-access-token:${GH_TOKEN}@github.com/CorvidLabs/homebrew-tap.git" /tmp/homebrew-tap
          cd /tmp/homebrew-tap

          # Rewrite the formula in-place
          python3 - <<'PY'
          import os, re, sys, pathlib
          p = pathlib.Path("Formula/fledge.rb")
          src = p.read_text()
          src = re.sub(
              r'(?m)^(\s*version\s+")(\d+\.\d+\.\d+)(")',
              rf'\g<1>{os.environ["NEW_VERSION"]}\g<3>',
              src,
              count=1,
          )
          shas = [
              os.environ["MACOS_AARCH64"],
              os.environ["MACOS_X86_64"],
              os.environ["LINUX_X86_64"],
          ]
          parts = re.split(r'(sha256\s+"[0-9a-fA-F]{64}")', src)
          if len(parts) - 1 != 6:
              sys.exit(
                  f"Expected 3 sha256 lines in Formula/fledge.rb, found {(len(parts) - 1) // 2}"
              )
          for i, sha in enumerate(shas):
              parts[2 * i + 1] = f'sha256 "{sha}"'
          p.write_text("".join(parts))
          PY

          git config user.name "github-actions[bot]"
          git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
          if git diff --quiet -- Formula/fledge.rb; then
            echo "homebrew-tap Formula/fledge.rb already at v$NEW_VERSION — nothing to do."
            exit 0
          fi
          git add Formula/fledge.rb
          git commit -m "chore: update formula to v$NEW_VERSION"
          git push origin main