From 9234fefb65ad7d4e7dcfb574cda8ae1d02953657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Halber?= Date: Wed, 27 May 2026 16:04:45 -0700 Subject: [PATCH] feat: package bt for homebrew --- .github/workflows/release-canary.yml | 2 +- .github/workflows/release.yml | 56 +++++++++++++++++++++++++++- Cargo.toml | 1 + README.md | 11 +++++- dist-workspace.toml | 10 ++++- src/self_update.rs | 2 +- 6 files changed, 75 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release-canary.yml b/.github/workflows/release-canary.yml index 4364e70e..04866c97 100644 --- a/.github/workflows/release-canary.yml +++ b/.github/workflows/release-canary.yml @@ -49,7 +49,7 @@ jobs: - name: Install dist shell: bash - run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.31.0/cargo-dist-installer.sh | sh" + run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.32.0/cargo-dist-installer.sh | sh" - name: Cache dist uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f32a75f8..a3fe9745 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -111,7 +111,7 @@ jobs: - name: Install dist if: steps.resolve-tag.outputs.should_release == 'true' shell: bash - run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.31.0/cargo-dist-installer.sh | sh" + run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.32.0/cargo-dist-installer.sh | sh" - name: Cache dist if: steps.resolve-tag.outputs.should_release == 'true' @@ -375,6 +375,60 @@ jobs: name: artifacts-dist-manifest path: dist-manifest.json + publish-homebrew-formula: + needs: + - plan + - host + if: ${{ needs.host.result == 'success' && !fromJson(needs.host.outputs.val).announcement_is_prerelease }} + runs-on: ubuntu-22.04 + env: + HOST_MANIFEST: ${{ needs.host.outputs.val }} + steps: + - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 + id: app-token + with: + app-id: ${{ vars.HOMEBREW_TAP_APP_ID }} + private-key: ${{ secrets.HOMEBREW_TAP_APP_PRIVATE_KEY }} + owner: braintrustdata + repositories: homebrew-tap + + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: true + repository: braintrustdata/homebrew-tap + token: ${{ steps.app-token.outputs.token }} + + - name: Fetch homebrew formula artifact + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: artifacts-build-global + path: Formula/ + + - name: Commit formula files + shell: bash + env: + GH_TOKEN: ${{ steps.app-token.outputs.token }} + APP_SLUG: ${{ steps.app-token.outputs.app-slug }} + run: | + user_id=$(gh api "/users/${APP_SLUG}%5Bbot%5D" --jq .id) + git config --global user.name "${APP_SLUG}[bot]" + git config --global user.email "${user_id}+${APP_SLUG}[bot]@users.noreply.github.com" + + export PATH="/home/linuxbrew/.linuxbrew/bin:$PATH" + brew update + + echo "$HOST_MANIFEST" | jq --compact-output '.releases[] | select([.artifacts[] | endswith(".rb")] | any)' | while IFS= read -r release; do + filename=$(echo "$release" | jq '.artifacts[] | select(endswith(".rb"))' --raw-output) + name=$(echo "$filename" | sed "s/\.rb$//") + version=$(echo "$release" | jq .app_version --raw-output) + + brew style --except-cops FormulaAudit/Homepage,FormulaAudit/Desc,FormulaAuditStrict --fix "Formula/${filename}" || true + + git add "Formula/${filename}" + git diff --quiet --cached -- "Formula/${filename}" || git commit -m "${name} ${version}" + done + git push + announce: needs: - plan diff --git a/Cargo.toml b/Cargo.toml index 5b4e014c..507d034d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ authors = ["Braintrust engineering "] description = "The Braintrust command line interface" license = "Apache-2.0" repository = "https://github.com/braintrustdata/bt" +homepage = "https://github.com/braintrustdata/bt" [package.metadata.wix] upgrade-guid = "5B558F98-EEBD-4F5E-A0C8-E7A039445139" diff --git a/README.md b/README.md index 932c72bf..dff96d13 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,14 @@ ### Unix (macOS / Linux) +Using homebrew: + +```bash +brew install braintrustdata/tap/bt +``` + +Using our installer script: + ```bash curl -fsSL https://bt.dev/cli/install.sh | bash ``` @@ -68,6 +76,7 @@ shasum -a 256 -c "bt-.tar.gz.sha256" ## Self Update `bt` can self-update when installed via the official installer. +If bt was installed via another package manager (Homebrew, cargo, npm...), use that package manager to update instead. ```bash # update on the current build channel (canary for local/dev builds, stable for official releases) @@ -80,8 +89,6 @@ bt self update --check bt self update --channel canary ``` -If `bt` was installed via another package manager (Homebrew, apt, choco, etc), use that package manager to update instead. - ## Uninstall Unix-like systems: diff --git a/dist-workspace.toml b/dist-workspace.toml index f4820f84..2b9e30fe 100644 --- a/dist-workspace.toml +++ b/dist-workspace.toml @@ -4,9 +4,10 @@ members = ["cargo:."] # Config for 'dist' [dist] # Skip checking whether the specified configuration files are up to date +# In our case, since we have heavily customised ci, prevent cargo dist from erasing our changes. allow-dirty = ["ci"] # The preferred dist version to use in CI (Cargo.toml SemVer syntax) -cargo-dist-version = "0.31.0" +cargo-dist-version = "0.32.0" # CI backends to support ci = "github" # Whether dist should create a Github Release or use an existing draft @@ -15,7 +16,12 @@ create-release = true pr-run-mode = "plan" # The installers to generate for each app installers = ["shell", "powershell"] -homepage = "https://github.com/braintrustdata/bt" +# Homebrew tap to publish the formula to (repo: github.com/braintrustdata/homebrew-tap) +tap = "braintrustdata/homebrew-tap" +formula = "bt" +# Technically does nothing as we allow dirty ci, which prevents `dist generate` from updating `.github/workflows/release.yml` +# Added in case we move our customization of the ci to another file and can use the auto-generated ci instead. +publish-jobs = ["homebrew"] # Target platforms to build apps for (Rust target-triple syntax) targets = ["aarch64-apple-darwin", "aarch64-unknown-linux-gnu", "aarch64-pc-windows-msvc", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu", "x86_64-unknown-linux-musl", "x86_64-pc-windows-msvc"] # Path that installers should place binaries in diff --git a/src/self_update.rs b/src/self_update.rs index bbac175f..c954e7f9 100644 --- a/src/self_update.rs +++ b/src/self_update.rs @@ -130,7 +130,7 @@ fn ensure_installer_managed_install() -> Result<()> { } anyhow::bail!( - "self-update is only supported for installer-based installs.\ncurrent executable: {}\nif this was installed with Homebrew/apt/choco/etc, update with that package manager", + "self-update is only supported for installer-based installs.\ncurrent executable: {}\nif this was installed with Homebrew/cargo/npm/..., update with that package manager", exe.display() ); }