Skip to content

Commit 058b6f8

Browse files
cameroncookeclaude
andcommitted
ci(homebrew): Automate tap formula updates
Add a Homebrew formula generator script and release workflow automation that computes artifact SHAs, generates Formula/xcodebuildmcp.rb, and opens a PR in cameroncooke/homebrew-xcodebuildmcp when credentials are configured. Keep the tap update flow token-gated and best-effort so releases continue when tap credentials are unavailable. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 7d14c35 commit 058b6f8

3 files changed

Lines changed: 157 additions & 0 deletions

File tree

.github/workflows/release.yml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,3 +339,71 @@ jobs:
339339
dist/portable/universal/xcodebuildmcp-${{ needs.release.outputs.version }}-darwin-universal.tar.gz \
340340
dist/portable/universal/xcodebuildmcp-${{ needs.release.outputs.version }}-darwin-universal.tar.gz.sha256 \
341341
--clobber
342+
343+
update_homebrew_tap:
344+
if: github.event_name == 'push'
345+
needs: [release, publish_portable_assets]
346+
runs-on: ubuntu-latest
347+
steps:
348+
- name: Checkout code
349+
uses: actions/checkout@v4
350+
351+
- name: Setup Node.js
352+
uses: actions/setup-node@v4
353+
with:
354+
node-version: '24'
355+
356+
- name: Download arm64 artifact
357+
uses: actions/download-artifact@v4
358+
with:
359+
name: portable-arm64
360+
path: dist/portable/arm64
361+
362+
- name: Download x64 artifact
363+
uses: actions/download-artifact@v4
364+
with:
365+
name: portable-x64
366+
path: dist/portable/x64
367+
368+
- name: Skip when tap token is unavailable
369+
if: secrets.HOMEBREW_TAP_TOKEN == ''
370+
run: echo "HOMEBREW_TAP_TOKEN is not set; skipping Homebrew tap update."
371+
372+
- name: Generate formula
373+
if: secrets.HOMEBREW_TAP_TOKEN != ''
374+
run: |
375+
VERSION="${{ needs.release.outputs.version }}"
376+
ARM64_SHA="$(awk '{print $1}' dist/portable/arm64/xcodebuildmcp-${VERSION}-darwin-arm64.tar.gz.sha256)"
377+
X64_SHA="$(awk '{print $1}' dist/portable/x64/xcodebuildmcp-${VERSION}-darwin-x64.tar.gz.sha256)"
378+
npm run homebrew:formula -- \
379+
--version "$VERSION" \
380+
--arm64-sha "$ARM64_SHA" \
381+
--x64-sha "$X64_SHA" \
382+
--out dist/homebrew/Formula/xcodebuildmcp.rb
383+
384+
- name: Create pull request in tap repo
385+
if: secrets.HOMEBREW_TAP_TOKEN != ''
386+
env:
387+
GH_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
388+
run: |
389+
VERSION="${{ needs.release.outputs.version }}"
390+
BRANCH="xcodebuildmcp-v${VERSION}"
391+
git clone "https://x-access-token:${GH_TOKEN}@github.com/cameroncooke/homebrew-xcodebuildmcp.git" tap-repo
392+
cp dist/homebrew/Formula/xcodebuildmcp.rb tap-repo/Formula/xcodebuildmcp.rb
393+
cd tap-repo
394+
if git diff --quiet Formula/xcodebuildmcp.rb; then
395+
echo "Formula already up to date; skipping PR."
396+
exit 0
397+
fi
398+
git checkout -b "$BRANCH"
399+
git config user.name "github-actions[bot]"
400+
git config user.email "github-actions[bot]@users.noreply.github.com"
401+
git add Formula/xcodebuildmcp.rb
402+
git commit -m "xcodebuildmcp ${VERSION}"
403+
git push origin "$BRANCH"
404+
gh pr create \
405+
--repo cameroncooke/homebrew-xcodebuildmcp \
406+
--title "Update xcodebuildmcp to ${VERSION}" \
407+
--body "Automated formula update for xcodebuildmcp ${VERSION}." \
408+
--base main \
409+
--head "$BRANCH"

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"package:macos": "scripts/package-macos-portable.sh",
2727
"package:macos:universal": "scripts/package-macos-portable.sh --universal",
2828
"verify:portable": "scripts/verify-portable-install.sh",
29+
"homebrew:formula": "scripts/create-homebrew-formula.sh",
2930
"lint": "eslint 'src/**/*.{js,ts}'",
3031
"lint:fix": "eslint 'src/**/*.{js,ts}' --fix",
3132
"format": "prettier --write 'src/**/*.{js,ts}'",

scripts/create-homebrew-formula.sh

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#!/usr/bin/env bash
2+
3+
set -euo pipefail
4+
5+
VERSION=""
6+
ARM64_SHA=""
7+
X64_SHA=""
8+
OUT_PATH=""
9+
10+
usage() {
11+
cat <<'EOF'
12+
Usage:
13+
scripts/create-homebrew-formula.sh --version <semver> --arm64-sha <sha256> --x64-sha <sha256> [--out <path>]
14+
EOF
15+
}
16+
17+
while [[ $# -gt 0 ]]; do
18+
case "$1" in
19+
--version)
20+
VERSION="${2:-}"
21+
shift 2
22+
;;
23+
--arm64-sha)
24+
ARM64_SHA="${2:-}"
25+
shift 2
26+
;;
27+
--x64-sha)
28+
X64_SHA="${2:-}"
29+
shift 2
30+
;;
31+
--out)
32+
OUT_PATH="${2:-}"
33+
shift 2
34+
;;
35+
-h|--help)
36+
usage
37+
exit 0
38+
;;
39+
*)
40+
echo "Unknown argument: $1"
41+
usage
42+
exit 1
43+
;;
44+
esac
45+
done
46+
47+
if [[ -z "$VERSION" || -z "$ARM64_SHA" || -z "$X64_SHA" ]]; then
48+
usage
49+
exit 1
50+
fi
51+
52+
FORMULA_CONTENT="$(cat <<EOF
53+
class Xcodebuildmcp < Formula
54+
desc "Model Context Protocol server for Xcode project workflows"
55+
homepage "https://github.com/cameroncooke/XcodeBuildMCP"
56+
license "MIT"
57+
version "$VERSION"
58+
59+
on_arm do
60+
url "https://github.com/cameroncooke/XcodeBuildMCP/releases/download/v$VERSION/xcodebuildmcp-$VERSION-darwin-arm64.tar.gz"
61+
sha256 "$ARM64_SHA"
62+
end
63+
64+
on_intel do
65+
url "https://github.com/cameroncooke/XcodeBuildMCP/releases/download/v$VERSION/xcodebuildmcp-$VERSION-darwin-x64.tar.gz"
66+
sha256 "$X64_SHA"
67+
end
68+
69+
def install
70+
libexec.install Dir["*"]
71+
bin.install_symlink libexec/"bin/xcodebuildmcp"
72+
bin.install_symlink libexec/"bin/xcodebuildmcp-doctor"
73+
end
74+
75+
test do
76+
assert_match "xcodebuildmcp", shell_output("#{bin}/xcodebuildmcp --help")
77+
end
78+
end
79+
EOF
80+
)"
81+
82+
if [[ -n "$OUT_PATH" ]]; then
83+
mkdir -p "$(dirname "$OUT_PATH")"
84+
printf "%s\n" "$FORMULA_CONTENT" > "$OUT_PATH"
85+
else
86+
printf "%s\n" "$FORMULA_CONTENT"
87+
fi
88+

0 commit comments

Comments
 (0)