200 lines
7.2 KiB
YAML
200 lines
7.2 KiB
YAML
name: Homebrew Cask Bump
|
|
|
|
# Why: keep the stablyai/homebrew-orca tap in sync with GitHub Releases.
|
|
# Triggers:
|
|
# - workflow_call → release-cut.yml finished publishing a stable tag
|
|
# - workflow_dispatch → manual backfill for a specific tag
|
|
#
|
|
# The job computes the sha256 of orca-macos-arm64.dmg + orca-macos-x64.dmg
|
|
# from the release, templates the channel-specific cask in this repo with the
|
|
# new version and hashes, then PRs the result into stablyai/homebrew-orca.
|
|
# Stable tags update Casks/orca.rb; RC tags update Casks/orca@rc.rb.
|
|
#
|
|
# Why no `release.published` trigger: other products shipped from this repo
|
|
# (e.g. mobile under `mobile-v*`) also publish GitHub Releases. A blanket
|
|
# `release.published` trigger would fire this workflow for any of them and
|
|
# attempt to download `orca-macos-*.dmg` from a non-desktop release, at
|
|
# best 404ing and at worst (if the filter were weaker) rewriting the cask
|
|
# to a non-desktop version. The tap is only ever bumped by the desktop
|
|
# release pipeline calling this workflow directly.
|
|
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
tag:
|
|
description: Release tag to sync (e.g. v1.3.25)
|
|
required: true
|
|
type: string
|
|
workflow_dispatch:
|
|
inputs:
|
|
tag:
|
|
description: Release tag to sync (e.g. v1.3.25)
|
|
required: true
|
|
type: string
|
|
|
|
jobs:
|
|
bump-cask:
|
|
runs-on: ubuntu-latest
|
|
# Why: only desktop tags have the macOS DMGs this workflow downloads.
|
|
# A mobile tag such as `mobile-v0.0.1` must never rewrite either cask.
|
|
if: >
|
|
inputs.tag != '' &&
|
|
startsWith(inputs.tag, 'v')
|
|
permissions:
|
|
contents: read
|
|
steps:
|
|
- name: Checkout orca
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Resolve tag and version
|
|
id: tag
|
|
env:
|
|
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
|
INPUT_TAG: ${{ inputs.tag }}
|
|
run: |
|
|
set -euo pipefail
|
|
if [[ -n "$INPUT_TAG" ]]; then
|
|
tag="$INPUT_TAG"
|
|
else
|
|
tag="$RELEASE_TAG"
|
|
fi
|
|
version="${tag#v}"
|
|
echo "tag=$tag" >>"$GITHUB_OUTPUT"
|
|
echo "version=$version" >>"$GITHUB_OUTPUT"
|
|
|
|
- name: Resolve cask target
|
|
id: cask
|
|
env:
|
|
TAG: ${{ steps.tag.outputs.tag }}
|
|
VERSION: ${{ steps.tag.outputs.version }}
|
|
run: |
|
|
set -euo pipefail
|
|
if [[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+-rc\.[0-9]+$ ]]; then
|
|
token="orca@rc"
|
|
branch_token="orca-rc"
|
|
elif [[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
token="orca"
|
|
branch_token="orca"
|
|
else
|
|
echo "::error::Unsupported desktop tag shape: $TAG" >&2
|
|
exit 1
|
|
fi
|
|
|
|
path="Casks/${token}.rb"
|
|
if [[ ! -f "$path" ]]; then
|
|
echo "::error::Missing cask template: $path" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "token=$token" >>"$GITHUB_OUTPUT"
|
|
echo "path=$path" >>"$GITHUB_OUTPUT"
|
|
echo "branch=bump/${branch_token}-${VERSION}" >>"$GITHUB_OUTPUT"
|
|
echo "title=${token} ${VERSION}" >>"$GITHUB_OUTPUT"
|
|
|
|
- name: Download DMGs and compute sha256
|
|
id: hash
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
TAG: ${{ steps.tag.outputs.tag }}
|
|
run: |
|
|
set -euo pipefail
|
|
mkdir -p dmgs
|
|
gh release download "$TAG" \
|
|
--repo "${{ github.repository }}" \
|
|
--pattern 'orca-macos-arm64.dmg' \
|
|
--pattern 'orca-macos-x64.dmg' \
|
|
--dir dmgs
|
|
arm=$(sha256sum dmgs/orca-macos-arm64.dmg | awk '{print $1}')
|
|
intel=$(sha256sum dmgs/orca-macos-x64.dmg | awk '{print $1}')
|
|
echo "arm=$arm" >>"$GITHUB_OUTPUT"
|
|
echo "intel=$intel" >>"$GITHUB_OUTPUT"
|
|
|
|
- name: Render updated cask file
|
|
env:
|
|
VERSION: ${{ steps.tag.outputs.version }}
|
|
ARM_SHA: ${{ steps.hash.outputs.arm }}
|
|
INTEL_SHA: ${{ steps.hash.outputs.intel }}
|
|
CASK_PATH: ${{ steps.cask.outputs.path }}
|
|
run: |
|
|
set -euo pipefail
|
|
python3 - <<'PY'
|
|
import os, re, pathlib
|
|
p = pathlib.Path(os.environ["CASK_PATH"])
|
|
src = p.read_text()
|
|
src = re.sub(r'version "[^"]+"',
|
|
f'version "{os.environ["VERSION"]}"', src, count=1)
|
|
src = re.sub(r'sha256 arm:\s*"[0-9a-f]+",\s*\n\s*intel:\s*"[0-9a-f]+"',
|
|
'sha256 arm: "{arm}",\n intel: "{intel}"'.format(
|
|
arm=os.environ["ARM_SHA"],
|
|
intel=os.environ["INTEL_SHA"]),
|
|
src, count=1)
|
|
p.write_text(src)
|
|
print(src)
|
|
PY
|
|
|
|
# Why: reuse the existing buf0-bot GitHub App (also used by
|
|
# track-community-prs.yaml) instead of minting a new PAT. The app is
|
|
# installed org-wide, so it has access to stablyai/homebrew-orca
|
|
# automatically. GITHUB_TOKEN cannot push cross-repo; a short-lived
|
|
# installation token can.
|
|
- name: Generate buf0-bot token
|
|
id: app-token
|
|
uses: actions/create-github-app-token@v3
|
|
with:
|
|
app-id: 2590194
|
|
private-key: ${{ secrets.BUFO_BOT_PRIVATE_KEY }}
|
|
owner: stablyai
|
|
repositories: homebrew-orca
|
|
|
|
- name: Checkout tap
|
|
uses: actions/checkout@v6
|
|
with:
|
|
repository: stablyai/homebrew-orca
|
|
path: tap
|
|
token: ${{ steps.app-token.outputs.token }}
|
|
|
|
- name: Copy cask into tap and open PR
|
|
env:
|
|
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
|
VERSION: ${{ steps.tag.outputs.version }}
|
|
TAG: ${{ steps.tag.outputs.tag }}
|
|
CASK_PATH: ${{ steps.cask.outputs.path }}
|
|
BRANCH: ${{ steps.cask.outputs.branch }}
|
|
TITLE: ${{ steps.cask.outputs.title }}
|
|
run: |
|
|
set -euo pipefail
|
|
mkdir -p "tap/$(dirname "$CASK_PATH")"
|
|
cp "$CASK_PATH" "tap/$CASK_PATH"
|
|
|
|
cd tap
|
|
# Why: commit author must match the buf0-bot app so commits are
|
|
# attributed to the bot in the tap's history / PR UI.
|
|
git config user.name "buf0-bot[bot]"
|
|
git config user.email "252831055+buf0-bot[bot]@users.noreply.github.com"
|
|
|
|
if git diff --quiet; then
|
|
echo "Cask already up-to-date for $TAG; nothing to do."
|
|
exit 0
|
|
fi
|
|
|
|
branch="$BRANCH"
|
|
git checkout -b "$branch"
|
|
git add "$CASK_PATH"
|
|
git commit -m "$TITLE"
|
|
git push -u origin "$branch" --force
|
|
|
|
# Why: repeated backfills can race an existing PR branch, so edit
|
|
# the PR title if creation reports that one already exists.
|
|
gh pr create \
|
|
--title "$TITLE" \
|
|
--body "Automated bump of $CASK_PATH from stablyai/orca release $TAG." \
|
|
--base main \
|
|
--head "$branch" \
|
|
|| gh pr edit "$branch" --title "$TITLE"
|
|
|
|
# Why: squash-merge immediately rather than --auto. The tap has no
|
|
# required checks or branch protection, and `gh pr merge --auto`
|
|
# only activates when there's something to wait on — on a repo
|
|
# with no gates it silently no-ops, leaving the PR open forever.
|
|
gh pr merge "$branch" --squash --delete-branch
|