From 8ff6018a4404e30dc4fba13c116241ef78ca72f6 Mon Sep 17 00:00:00 2001 From: ChiragAgg5k Date: Fri, 17 Apr 2026 17:31:00 +0530 Subject: [PATCH] chore: migrate Homebrew install to appwrite/homebrew-appwrite tap Companion to appwrite/sdk-generator#1459. Drops the stub `Formula/appwrite.rb` (sdk-for-cli is not a Homebrew tap, so `brew install` never actually worked against this repo) and rewires the release flow to the dedicated tap at appwrite/homebrew-appwrite. - Remove `Formula/appwrite.rb`. The canonical formula now lives in appwrite/homebrew-appwrite (generated there on bootstrap). - Replace the "Update Homebrew formula checksums" step with a tap-PR flow: check out appwrite/homebrew-appwrite with a new HOMEBREW_TAP_GH_TOKEN secret, recompute SHA256s for the four native binaries, patch the formula in place, and open (or update) a PR on the tap. - README: switch install command to `brew install appwrite/appwrite/appwrite` and link out to the tap repo; the section now covers both macOS and Linux. - lib/constants.ts: add HOMEBREW_TAP + HOMEBREW_FORMULA so self-update and `brew info` consistently use the fully-qualified `/` form. - lib/utils.ts, lib/commands/update.ts: use HOMEBREW_FORMULA everywhere we previously hardcoded `appwrite`. Requires the new `HOMEBREW_TAP_GH_TOKEN` secret (fine-grained PAT with `contents: write` + `pull-requests: write` on appwrite/homebrew-appwrite) to be added to this repo before the next release. --- .github/workflows/publish.yml | 82 +++++++++++++++++++++++++---------- Formula/appwrite.rb | 68 ----------------------------- README.md | 6 +-- lib/commands/update.ts | 13 +++--- lib/constants.ts | 4 ++ lib/utils.ts | 4 +- 6 files changed, 77 insertions(+), 100 deletions(-) delete mode 100644 Formula/appwrite.rb diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 0c2fb84..0a91f73 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -17,6 +17,7 @@ jobs: # them on launch (oven-sh/bun#29120). Unpin once a Bun release includes the # upstream fix (oven-sh/bun#29122). CLI_BUN_VERSION: '1.3.11' + HOMEBREW_TAP_REPO: appwrite/homebrew-appwrite steps: - uses: actions/checkout@v4 with: @@ -75,33 +76,34 @@ jobs: GHR_REPLACE: false GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} - - name: Update Homebrew formula checksums + - name: Check out Homebrew tap + uses: actions/checkout@v4 + with: + repository: ${{ env.HOMEBREW_TAP_REPO }} + token: ${{ secrets.HOMEBREW_TAP_GH_TOKEN }} + path: homebrew-tap + fetch-depth: 0 + + - name: Update Homebrew formula in tap + id: tap + working-directory: homebrew-tap env: RELEASE_TAG: ${{ github.event.release.tag_name }} - TARGET_COMMITISH: ${{ github.event.release.target_commitish }} run: | set -euo pipefail - TARGET_BRANCH="$TARGET_COMMITISH" - if ! git ls-remote --exit-code --heads origin "$TARGET_BRANCH" >/dev/null 2>&1; then - TARGET_BRANCH="master" - fi - - git fetch origin "$TARGET_BRANCH" - git switch -C "$TARGET_BRANCH" "origin/$TARGET_BRANCH" - FORMULA_PATH="$(find Formula -maxdepth 1 -name '*.rb' | head -n 1)" if [ -z "$FORMULA_PATH" ]; then - echo "Formula file not found" + echo "No formula found in Homebrew tap" exit 1 fi - EXECUTABLE_NAME="$(basename "$FORMULA_PATH" .rb)" - export FORMULA_PATH RELEASE_TAG EXECUTABLE_NAME - export MAC_ARM64_SHA256="$(sha256sum "build/${EXECUTABLE_NAME}-cli-darwin-arm64" | awk '{print $1}')" - export MAC_X64_SHA256="$(sha256sum "build/${EXECUTABLE_NAME}-cli-darwin-x64" | awk '{print $1}')" - export LINUX_ARM64_SHA256="$(sha256sum "build/${EXECUTABLE_NAME}-cli-linux-arm64" | awk '{print $1}')" - export LINUX_X64_SHA256="$(sha256sum "build/${EXECUTABLE_NAME}-cli-linux-x64" | awk '{print $1}')" + + export FORMULA_PATH EXECUTABLE_NAME + export MAC_ARM64_SHA256="$(sha256sum "../build/${EXECUTABLE_NAME}-cli-darwin-arm64" | awk '{print $1}')" + export MAC_X64_SHA256="$(sha256sum "../build/${EXECUTABLE_NAME}-cli-darwin-x64" | awk '{print $1}')" + export LINUX_ARM64_SHA256="$(sha256sum "../build/${EXECUTABLE_NAME}-cli-linux-arm64" | awk '{print $1}')" + export LINUX_X64_SHA256="$(sha256sum "../build/${EXECUTABLE_NAME}-cli-linux-x64" | awk '{print $1}')" ruby <<'RUBY' formula_path = ENV.fetch("FORMULA_PATH") @@ -132,13 +134,49 @@ jobs: ruby -c "$FORMULA_PATH" + { + echo "executable=${EXECUTABLE_NAME}" + echo "formula_path=${FORMULA_PATH}" + } >> "$GITHUB_OUTPUT" + + - name: Open pull request on Homebrew tap + working-directory: homebrew-tap + env: + RELEASE_TAG: ${{ github.event.release.tag_name }} + EXECUTABLE_NAME: ${{ steps.tap.outputs.executable }} + FORMULA_PATH: ${{ steps.tap.outputs.formula_path }} + SOURCE_REPO: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GH_TOKEN: ${{ secrets.HOMEBREW_TAP_GH_TOKEN }} + run: | + set -euo pipefail + if git diff --quiet -- "$FORMULA_PATH"; then - echo "Homebrew formula already up to date" + echo "Homebrew formula already up to date for ${RELEASE_TAG}" exit 0 fi - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + BASE_BRANCH="$(gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name')" + BRANCH="release/${EXECUTABLE_NAME}-${RELEASE_TAG}" + + git config user.name "appwrite-bot" + git config user.email "bot@appwrite.io" + + git checkout -B "$BRANCH" git add "$FORMULA_PATH" - git commit -m "chore: update Homebrew formula for ${RELEASE_TAG}" - git push origin "$TARGET_BRANCH" + git commit -m "${EXECUTABLE_NAME} ${RELEASE_TAG}" + git push -f -u origin "$BRANCH" + + PR_TITLE="${EXECUTABLE_NAME} ${RELEASE_TAG}" + PR_BODY=$(printf 'Automated formula update for the `%s` CLI release [`%s`](%s/%s/releases/tag/%s).\n\nOpened automatically by the `%s` publish workflow after release binaries were uploaded.' "$EXECUTABLE_NAME" "$RELEASE_TAG" "$SERVER_URL" "$SOURCE_REPO" "$RELEASE_TAG" "${SOURCE_REPO#*/}") + + EXISTING_PR="$(gh pr list --head "$BRANCH" --state open --json number --jq '.[0].number' || true)" + if [ -n "$EXISTING_PR" ]; then + gh pr edit "$EXISTING_PR" --title "$PR_TITLE" --body "$PR_BODY" + else + gh pr create \ + --title "$PR_TITLE" \ + --body "$PR_BODY" \ + --base "$BASE_BRANCH" \ + --head "$BRANCH" + fi diff --git a/Formula/appwrite.rb b/Formula/appwrite.rb deleted file mode 100644 index 59b5af4..0000000 --- a/Formula/appwrite.rb +++ /dev/null @@ -1,68 +0,0 @@ -class Appwrite < Formula - desc "Command-line tool for interacting with the Appwrite API" - homepage "https://appwrite.io" - license "BSD-3-Clause" - version "18.2.0" - - def self.binary_arch - Hardware::CPU.arm? ? "arm64" : "x64" - end - - def self.binary_os - return "darwin" if OS.mac? - return "linux" if OS.linux? - - raise "Homebrew formula is only supported on macOS and Linux" - end - - def self.binary_name - "appwrite-cli-#{binary_os}-#{binary_arch}" - end - - def self.build_target - return "mac-#{binary_arch}" if OS.mac? - return "linux-#{binary_arch}" if OS.linux? - - raise "Homebrew formula is only supported on macOS and Linux" - end - - # Release automation injects per-target SHA256 values when publishing binaries. - on_macos do - if Hardware::CPU.arm? - url "https://github.com/appwrite/sdk-for-cli/releases/download/#{version}/appwrite-cli-darwin-arm64" - sha256 "14ea83b1fc962b7be91c7a6e8723f83369b5ce0e6b3f56f61093cd00381ac086" - else - url "https://github.com/appwrite/sdk-for-cli/releases/download/#{version}/appwrite-cli-darwin-x64" - sha256 "83703a86d2cb22966beb4afd0f88f11319ca81fbf64a91e9e0f8d6375d4506d4" - end - end - - on_linux do - if Hardware::CPU.arm? - url "https://github.com/appwrite/sdk-for-cli/releases/download/#{version}/appwrite-cli-linux-arm64" - sha256 "d215cd4c1f0b70916436d7061797d407a7b0ce9830cfc29aa735b1405dafbd00" - else - url "https://github.com/appwrite/sdk-for-cli/releases/download/#{version}/appwrite-cli-linux-x64" - sha256 "38c127e173b5ea2e5b2f170979681156cd30060e39960cefb9a7abfda3353988" - end - end - - head "https://github.com/appwrite/sdk-for-cli.git", branch: "master" do - depends_on "bun" => :build - end - - def install - if build.head? - system "bun", "install", "--frozen-lockfile" - system "bun", "run", self.class.build_target - bin.install "build/#{self.class.binary_name}" => "appwrite" - return - end - - bin.install self.class.binary_name => "appwrite" - end - - test do - assert_match "Usage:", shell_output("#{bin}/appwrite --help") - end -end diff --git a/README.md b/README.md index aa6accf..c2e93b6 100644 --- a/README.md +++ b/README.md @@ -42,12 +42,12 @@ If you do not have `npm` installed, you can always install the prebuilt binaries $ wget -q https://appwrite.io/cli/install.sh -O - | /bin/bash ``` -### MacOS via [Homebrew](https://brew.sh) +### MacOS / Linux via [Homebrew](https://brew.sh) ```bash -$ brew install appwrite +$ brew install appwrite/appwrite/appwrite ``` -Homebrew installs the native binary for your platform. +Homebrew pulls the formula from the [`appwrite/homebrew-appwrite`](https://github.com/appwrite/homebrew-appwrite) tap and downloads the native binary for your platform. ### Windows Via Powershell diff --git a/lib/commands/update.ts b/lib/commands/update.ts index dc77b31..a015560 100644 --- a/lib/commands/update.ts +++ b/lib/commands/update.ts @@ -15,6 +15,7 @@ import { import { EXECUTABLE_NAME, GITHUB_RELEASES_URL, + HOMEBREW_FORMULA, NPM_PACKAGE_NAME, SDK_TITLE, } from "../constants.js"; @@ -164,10 +165,10 @@ const updateViaNpm = async (): Promise => { */ const updateViaHomebrew = async (): Promise => { try { - await execCommand("brew", ["upgrade", "appwrite"]); + await execCommand("brew", ["upgrade", HOMEBREW_FORMULA]); console.log(""); success("Updated to latest version via Homebrew!"); - hint("Run 'appwrite --version' to verify the new version."); + hint(`Run '${EXECUTABLE_NAME} --version' to verify the new version.`); } catch (e: unknown) { const message = getErrorMessage(e); @@ -177,11 +178,13 @@ const updateViaHomebrew = async (): Promise => { ) { console.log(""); success("Latest version is already installed via Homebrew!"); - hint("The CLI is up to date. Run 'appwrite --version' to verify."); + hint( + `The CLI is up to date. Run '${EXECUTABLE_NAME} --version' to verify.`, + ); } else { console.log(""); error(`Failed to update via Homebrew: ${message}`); - hint("Try running: brew upgrade appwrite"); + hint(`Try running: brew upgrade ${HOMEBREW_FORMULA}`); } } }; @@ -258,7 +261,7 @@ const showManualInstructions = (latestVersion: string): void => { console.log(""); log(`${chalk.bold("Option 2: Homebrew")}`); - console.log(` brew upgrade appwrite`); + console.log(` brew upgrade ${HOMEBREW_FORMULA}`); console.log(""); if (process.platform !== "win32") { diff --git a/lib/constants.ts b/lib/constants.ts index c240567..0db7234 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -12,6 +12,10 @@ export const EXECUTABLE_NAME = 'appwrite'; // 1 day export const UPDATE_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000; +// Homebrew — fully-qualified `//` reference +export const HOMEBREW_TAP = 'appwrite/appwrite'; +export const HOMEBREW_FORMULA = `${HOMEBREW_TAP}/appwrite`; + // NPM export const NPM_PACKAGE_NAME = 'appwrite-cli'; export const NPM_REGISTRY_URL = `https://registry.npmjs.org/${NPM_PACKAGE_NAME}/latest`; diff --git a/lib/utils.ts b/lib/utils.ts index 519187a..ffaedd2 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -12,6 +12,7 @@ import { NPM_PACKAGE_NAME, DEFAULT_ENDPOINT, EXECUTABLE_NAME, + HOMEBREW_FORMULA, UPDATE_CHECK_INTERVAL_MS, } from "./constants.js"; @@ -102,7 +103,6 @@ type HomebrewInfoResponse = { }; const WINDOWS_EXECUTABLE_NAME = `${EXECUTABLE_NAME.toLowerCase()}.exe`; -const HOMEBREW_FORMULA_NAME = EXECUTABLE_NAME.toLowerCase(); const getExecutablePaths = (): { execPath: string; @@ -227,7 +227,7 @@ const getHomebrewLatestVersion = async ( try { const output = childProcess.execFileSync( "brew", - ["info", "--json=v2", HOMEBREW_FORMULA_NAME], + ["info", "--json=v2", HOMEBREW_FORMULA], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"],