ci: auto-bump Homebrew tap on stable release tags (#938) (#976)
Some checks failed
build-packages / dedupe push run (push) Has been cancelled
build-packages / dedupe result (push) Has been cancelled
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / ${{ needs.dedupe.outputs.skip_heavy_ci == 'true' && 'deduped build-linux-x64' || 'build-linux-x64' }} (push) Has been cancelled
build-packages / ${{ needs.dedupe.outputs.skip_heavy_ci == 'true' && 'deduped build-linux-arm64' || 'build-linux-arm64' }} (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
Some checks failed
build-packages / dedupe push run (push) Has been cancelled
build-packages / dedupe result (push) Has been cancelled
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / ${{ needs.dedupe.outputs.skip_heavy_ci == 'true' && 'deduped build-linux-x64' || 'build-linux-x64' }} (push) Has been cancelled
build-packages / ${{ needs.dedupe.outputs.skip_heavy_ci == 'true' && 'deduped build-linux-arm64' || 'build-linux-arm64' }} (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
After the GitHub Release is published, push an updated Cask to binaricat/homebrew-netcatty so `brew install binaricat/netcatty/netcatty` stays current within minutes of the release. Stable tags only — prerelease tags (v1.2.0-rc.1 etc.) are skipped to keep brew users on stable. Implementation: - New script .github/scripts/bump-homebrew-cask.sh computes SHA-256 of the arm64 + x64 DMGs already downloaded by the release job, sed-patches the Cask file in the tap repo, sanity-checks the result parses as Ruby, and pushes the bump. Idempotent on re-run when checksums match. - New homebrew-tap job in build.yml runs after the release job on the same stable-tag gate, downloads the macOS artifact bundle, then runs the bump script with HOMEBREW_TAP_TOKEN. Requires HOMEBREW_TAP_TOKEN secret with contents:write on binaricat/homebrew-netcatty. With the secret missing the job will fail fast at the env-var check with no side effects (no push attempted). Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
89
.github/scripts/bump-homebrew-cask.sh
vendored
Executable file
89
.github/scripts/bump-homebrew-cask.sh
vendored
Executable file
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# bump-homebrew-cask.sh — push a new version of the Netcatty cask to the
|
||||
# binaricat/homebrew-netcatty tap.
|
||||
#
|
||||
# Called from the release pipeline (`build.yml` → `homebrew-tap` job) after
|
||||
# the GitHub Release has been published with the signed + notarized DMGs.
|
||||
# Computes SHA-256 of the arm64 and x64 DMGs, rewrites the cask file, and
|
||||
# pushes the bump back to the tap repository using HOMEBREW_TAP_TOKEN.
|
||||
#
|
||||
# Required env vars:
|
||||
# VERSION — semver without leading "v" (e.g. 1.1.6)
|
||||
# HOMEBREW_TAP_TOKEN — PAT with contents:write on the tap repo
|
||||
#
|
||||
# Optional env vars:
|
||||
# TAP_REPO — default: binaricat/homebrew-netcatty
|
||||
# ARTIFACTS_DIR — default: artifacts
|
||||
# CASK_PATH — default: Casks/netcatty.rb
|
||||
set -euo pipefail
|
||||
|
||||
: "${VERSION:?VERSION env var required (no leading v)}"
|
||||
: "${HOMEBREW_TAP_TOKEN:?HOMEBREW_TAP_TOKEN env var required}"
|
||||
|
||||
TAP_REPO="${TAP_REPO:-binaricat/homebrew-netcatty}"
|
||||
ARTIFACTS_DIR="${ARTIFACTS_DIR:-artifacts}"
|
||||
CASK_PATH="${CASK_PATH:-Casks/netcatty.rb}"
|
||||
|
||||
ARM_DMG="${ARTIFACTS_DIR}/Netcatty-${VERSION}-mac-arm64.dmg"
|
||||
X64_DMG="${ARTIFACTS_DIR}/Netcatty-${VERSION}-mac-x64.dmg"
|
||||
|
||||
for f in "$ARM_DMG" "$X64_DMG"; do
|
||||
if [[ ! -f "$f" ]]; then
|
||||
echo "::error::Required DMG artifact not found: $f"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
ARM_SHA=$(shasum -a 256 "$ARM_DMG" | awk '{print $1}')
|
||||
X64_SHA=$(shasum -a 256 "$X64_DMG" | awk '{print $1}')
|
||||
|
||||
echo "Computed checksums:"
|
||||
echo " arm64: ${ARM_SHA}"
|
||||
echo " x64 : ${X64_SHA}"
|
||||
|
||||
TMP=$(mktemp -d)
|
||||
trap 'rm -rf "$TMP"' EXIT
|
||||
|
||||
git clone --depth 1 \
|
||||
"https://x-access-token:${HOMEBREW_TAP_TOKEN}@github.com/${TAP_REPO}.git" \
|
||||
"$TMP/tap"
|
||||
cd "$TMP/tap"
|
||||
|
||||
if [[ ! -f "$CASK_PATH" ]]; then
|
||||
echo "::error::Cask file not found in tap: $CASK_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Patch the cask in place. The three lines we touch are anchored well enough
|
||||
# that we don't need anything fancier than sed:
|
||||
# - the `version "X.Y.Z"` line (single line, anchored to start)
|
||||
# - the `sha256 arm: "..."` line
|
||||
# - the ` intel: "..."` line (anchor on "intel:" at start, after the
|
||||
# leading whitespace, so we don't accidentally match the `arch arm:
|
||||
# "...", intel: "..."` line earlier in the file)
|
||||
sed -i -E 's|^(\s*version)\s+"[^"]+"|\1 "'"$VERSION"'"|' "$CASK_PATH"
|
||||
sed -i -E 's|(sha256\s+arm:\s+)"[^"]+"|\1"'"$ARM_SHA"'"|' "$CASK_PATH"
|
||||
sed -i -E 's|^(\s*intel:\s+)"[^"]+"|\1"'"$X64_SHA"'"|' "$CASK_PATH"
|
||||
|
||||
# Sanity-check: parsed file should still be valid Ruby. Catches a broken
|
||||
# substitution before we push.
|
||||
if command -v ruby >/dev/null 2>&1; then
|
||||
ruby -c "$CASK_PATH" >/dev/null
|
||||
fi
|
||||
|
||||
if git diff --quiet; then
|
||||
echo "Cask already at ${VERSION} with matching checksums — nothing to push."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Cask diff:"
|
||||
git --no-pager diff "$CASK_PATH"
|
||||
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git config user.name "github-actions[bot]"
|
||||
git add "$CASK_PATH"
|
||||
git commit -m "Bump netcatty to ${VERSION}"
|
||||
git push origin HEAD:main
|
||||
|
||||
echo "Pushed bump for ${VERSION} to ${TAP_REPO}."
|
||||
30
.github/workflows/build.yml
vendored
30
.github/workflows/build.yml
vendored
@@ -604,3 +604,33 @@ jobs:
|
||||
generate_release_notes: true
|
||||
fail_on_unmatched_files: false
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
|
||||
homebrew-tap:
|
||||
name: bump homebrew tap
|
||||
runs-on: ubuntu-latest
|
||||
needs: release
|
||||
# Only stable release tags update the Cask. Prerelease tags
|
||||
# (e.g. v1.2.0-rc.1) are skipped so brew users stay on stable.
|
||||
if: |
|
||||
startsWith(github.ref, 'refs/tags/v')
|
||||
&& !contains(github.ref_name, '-')
|
||||
&& (github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.publish_release))
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download macOS artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: netcatty-macos
|
||||
path: artifacts/
|
||||
|
||||
- name: Bump Cask in binaricat/homebrew-netcatty
|
||||
env:
|
||||
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
|
||||
ARTIFACTS_DIR: artifacts
|
||||
run: |
|
||||
# Strip the leading "v" — Cask version is plain semver.
|
||||
VERSION="${GITHUB_REF_NAME#v}"
|
||||
export VERSION
|
||||
bash .github/scripts/bump-homebrew-cask.sh
|
||||
|
||||
Reference in New Issue
Block a user