ci: auto-bump Homebrew formula on CLI release#3306
Conversation
When a cli-v* tag is published as a GitHub Release: 1. Compute SHA256 for each platform tarball 2. Rewrite Formula/superset.rb with the new version and SHAs 3. Push to superset-sh/homebrew-tap Requires a HOMEBREW_TAP_TOKEN secret (GitHub PAT with repo access to superset-sh/homebrew-tap).
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds a GitHub Actions workflow to bump a Homebrew tap on Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Release as GitHub Release
participant Actions as GitHub Actions Runner
participant Artifacts as Superset Release Assets
participant Tap as Homebrew Tap Repo
Release->>Actions: release.published (tag cli-v*)
Actions->>Actions: validate tag & extract version
Actions->>Artifacts: download darwin-arm64 / darwin-x64 / linux-x64 tarballs
Artifacts-->>Actions: return tarball files
Actions->>Actions: compute SHA256s
Actions->>Tap: checkout/clone tap using token
Actions->>Tap: render/overwrite Formula/superset.rb (version + SHA256s)
Actions->>Tap: commit & push (retry: git pull --rebase && push)
Tap-->>Actions: push result
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryThis PR adds
Confidence Score: 3/5Not safe to merge until the pipe-failure bug and script-injection issue are fixed; both are straightforward one-line corrections. Two P1 issues: (1) missing .github/workflows/bump-homebrew.yml — all three issues are in this single file.
|
| Filename | Overview |
|---|---|
| .github/workflows/bump-homebrew.yml | New CI workflow that auto-bumps the Homebrew tap on CLI release publication; has a P1 pipe-failure bug that silently writes a wrong SHA, a P1 script-injection risk in the tag extraction step, and a P2 formula indentation issue from the heredoc inside a YAML block. |
Sequence Diagram
sequenceDiagram
participant Dev as Developer
participant GH as GitHub (superset-sh/superset)
participant Workflow as bump-homebrew.yml
participant Releases as GitHub Releases CDN
participant Tap as superset-sh/homebrew-tap
Dev->>GH: Push cli-v* tag
GH->>GH: build-cli.yml builds tarballs & creates draft release
Dev->>GH: Publish draft release
GH->>Workflow: release.published event (tag starts with cli-v)
Workflow->>Workflow: Extract version from tag
loop for each platform tarball
Workflow->>Releases: curl download tarball
Releases-->>Workflow: tarball bytes
Workflow->>Workflow: shasum -a 256 → SHA256
end
Workflow->>Tap: checkout via HOMEBREW_TAP_TOKEN
Workflow->>Tap: Rewrite Formula/superset.rb (version + SHAs)
Workflow->>Tap: git commit & push
Note over Tap: brew install superset-sh/tap/superset now works
Reviews (1): Last reviewed commit: "ci: auto-bump Homebrew formula on CLI re..." | Re-trigger Greptile
| sha=$(curl -fsSL "$url" | shasum -a 256 | awk '{print $1}') | ||
| if [ -z "$sha" ]; then | ||
| echo "::error::Failed to compute SHA for $target" |
There was a problem hiding this comment.
Pipe failure silently produces wrong SHA
Without set -o pipefail, a curl failure (e.g. 404 because the tarball hasn't been attached yet, or a network error) doesn't terminate the script. shasum still receives empty input and emits e3b0c44298fc1c149afbf4c8996fb92427ae41e4 — the SHA256 of zero bytes — which is non-empty, so the if [ -z "$sha" ] guard on line 33 is bypassed. The formula would be updated with a bogus checksum and brew install would fail for every user.
Add set -euo pipefail at the top of this step's run block:
| sha=$(curl -fsSL "$url" | shasum -a 256 | awk '{print $1}') | |
| if [ -z "$sha" ]; then | |
| echo "::error::Failed to compute SHA for $target" | |
| run: | | |
| set -euo pipefail | |
| for target in darwin-arm64 darwin-x64 linux-x64; do | |
| url="https://github.com/superset-sh/superset/releases/download/${TAG}/superset-${target}.tar.gz" | |
| echo "Fetching SHA for $url" | |
| sha=$(curl -fsSL "$url" | shasum -a 256 | awk '{print $1}') | |
| if [ -z "$sha" ]; then | |
| echo "::error::Failed to compute SHA for $target" | |
| exit 1 | |
| fi | |
| echo "${target//-/_}_sha=$sha" >> "$GITHUB_OUTPUT" | |
| done |
With pipefail, if curl returns a non-zero exit code (e.g. 22 for 404), the entire pipeline fails immediately and the if [ -z "$sha" ] branch becomes a useful secondary guard for any remaining edge cases.
| run: | | ||
| TAG="${{ github.event.release.tag_name }}" | ||
| VERSION="${TAG#cli-v}" | ||
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | ||
| echo "tag=$TAG" >> "$GITHUB_OUTPUT" |
There was a problem hiding this comment.
${{ github.event.release.tag_name }} is interpolated directly into the shell script by the Actions runner before the shell parses it. If a tag name were crafted with shell metacharacters (e.g. a backtick, $(...), or a double-quote), it could execute arbitrary code in the runner. GitHub's own security hardening guide explicitly flags this pattern as a script-injection vector.
The fix is to pass context values through an env: block so they arrive as environment variables — not as literal text spliced into the script:
| run: | | |
| TAG="${{ github.event.release.tag_name }}" | |
| VERSION="${TAG#cli-v}" | |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | |
| echo "tag=$TAG" >> "$GITHUB_OUTPUT" | |
| - name: Extract version from tag | |
| id: version | |
| env: | |
| TAG: ${{ github.event.release.tag_name }} | |
| run: | | |
| VERSION="${TAG#cli-v}" | |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | |
| echo "tag=$TAG" >> "$GITHUB_OUTPUT" |
This change is low-risk (git tags are restricted in practice) but it's a well-established best practice and keeps the workflow consistent with the shas step below, which already uses env: correctly.
| cat > Formula/superset.rb <<EOF | ||
| class Superset < Formula | ||
| desc "CLI and host-service for Superset" | ||
| homepage "https://superset.sh" | ||
| version "${VERSION}" | ||
| license "MIT" | ||
|
|
||
| on_macos do | ||
| on_arm do | ||
| url "https://github.com/superset-sh/superset/releases/download/cli-v#{version}/superset-darwin-arm64.tar.gz" | ||
| sha256 "${DARWIN_ARM64_SHA}" | ||
| end | ||
| on_intel do | ||
| url "https://github.com/superset-sh/superset/releases/download/cli-v#{version}/superset-darwin-x64.tar.gz" | ||
| sha256 "${DARWIN_X64_SHA}" | ||
| end | ||
| end | ||
|
|
||
| on_linux do | ||
| on_intel do | ||
| url "https://github.com/superset-sh/superset/releases/download/cli-v#{version}/superset-linux-x64.tar.gz" | ||
| sha256 "${LINUX_X64_SHA}" | ||
| end | ||
| end | ||
|
|
||
| def install | ||
| libexec.install Dir["*"] | ||
| bin.install_symlink libexec/"bin/superset" | ||
| bin.install_symlink libexec/"bin/superset-host" | ||
| end | ||
|
|
||
| test do | ||
| assert_match "superset", shell_output("#{bin}/superset --version") | ||
| end | ||
| end | ||
| EOF |
There was a problem hiding this comment.
Heredoc inherits YAML indentation, producing a malformed formula
The cat <<EOF block sits inside the YAML run: block at 10 spaces of indentation. Because heredoc content is captured verbatim (and <<-EOF only strips tabs, not spaces), every line of the resulting Formula/superset.rb will start with 10 extra leading spaces. While Ruby itself doesn't care about indentation, brew audit --strict (which Homebrew runs on tap formulas during CI) will reject non-standard whitespace and flag style errors.
The simplest fix is to strip the leading whitespace with sed after writing:
cat > Formula/superset.rb <<EOF
class Superset < Formula
...
end
EOF
# Strip the leading indentation added by the YAML block
sed -i 's/^ //' Formula/superset.rbAlternatively, extract the formula template into a separate file (e.g. .github/formula-template.rb) and use envsubst or sed substitutions — this keeps the YAML readable and the formula correctly formatted.
One-liner install for the CLI distribution: curl -fsSL https://superset.sh/cli/install.sh | sh - Detects platform/arch (macOS arm64/x64, Linux x64) - Downloads latest release tarball from GitHub - Extracts to ~/superset/ (or $SUPERSET_HOME) - Adds ~/superset/bin to PATH in the user's shell profile - Respects SUPERSET_VERSION for pinned installs Also: tarball no longer has a top-level superset-<target>/ wrapper, so `tar -xzf ... -C ~/superset` drops contents directly.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/bump-homebrew.yml:
- Around line 11-15: The bump job's push step currently does a straight git push
which can silently drop a release bump if two runs overlap; update the bump job
(the steps under jobs.bump that perform the git commit/push) to fetch the remote
branch and perform a git pull --rebase (or git fetch + git rebase
origin/<branch>) immediately before pushing, and wrap the push in a retry that
will re-fetch/rebase and re-apply the commit if a non-fast-forward error occurs
so concurrent runs serialize and don't lose updates.
- Around line 24-38: Add robust failure handling to the SHA computation step:
enable strict bash mode by adding set -euo pipefail at the top of the run block,
download each release artifact into a temporary file (e.g., using mktemp)
instead of piping directly into shasum, validate the downloaded file size is
non-zero (fail with an error if it is), compute the SHA256 from that file and
then write the result to GITHUB_OUTPUT using the same variable name pattern
(${target//-/_}_sha); ensure temporary files are removed after use.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: fc89c1a3-3ea1-4a8a-8fcb-cfd66f1f9993
📒 Files selected for processing (1)
.github/workflows/bump-homebrew.yml
🚀 Preview Deployment🔗 Preview Links
Preview updates automatically with new commits |
- Add set -euo pipefail to all run blocks
- Curl to tempfile + check exit status instead of piping to shasum
(pipes without pipefail mask curl failures and produce the
empty-input SHA256)
- Inject tag via env: instead of direct ${{ }} interpolation to
prevent script injection via malicious tag names. Validate tag
format with regex before use.
- Render formula via python3 reading from env, eliminating YAML+shell
heredoc indentation pitfalls
- Add concurrency group to serialize concurrent release publishes
- Retry push once with rebase as belt-and-suspenders
There was a problem hiding this comment.
2 issues found across 1 file
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name=".github/workflows/bump-homebrew.yml">
<violation number="1" location=".github/workflows/bump-homebrew.yml:19">
P1: `${{ github.event.release.tag_name }}` is interpolated directly into the shell script by the Actions runner before the shell parses it. A tag name with shell metacharacters (backticks, `$(...)`, etc.) could execute arbitrary code. Pass it through an `env:` block instead, matching the pattern already used in the `shas` step below.</violation>
<violation number="2" location=".github/workflows/bump-homebrew.yml:32">
P0: Without `set -o pipefail`, a `curl` failure (e.g., 404 for a missing tarball) is masked by the pipeline — `shasum` hashes the empty stdin and produces `e3b0c44298fc1c149afbf4c8996fb924...`, which is non-empty, so the `[ -z "$sha" ]` guard on the next line is silently bypassed. The formula would be pushed with a bogus checksum, breaking `brew install` for every user.
Add `set -euo pipefail` at the top of this step's `run:` block so any upstream pipe failure terminates the script immediately.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| for target in darwin-arm64 darwin-x64 linux-x64; do | ||
| url="https://github.com/superset-sh/superset/releases/download/${TAG}/superset-${target}.tar.gz" | ||
| echo "Fetching SHA for $url" | ||
| sha=$(curl -fsSL "$url" | shasum -a 256 | awk '{print $1}') |
There was a problem hiding this comment.
P0: Without set -o pipefail, a curl failure (e.g., 404 for a missing tarball) is masked by the pipeline — shasum hashes the empty stdin and produces e3b0c44298fc1c149afbf4c8996fb924..., which is non-empty, so the [ -z "$sha" ] guard on the next line is silently bypassed. The formula would be pushed with a bogus checksum, breaking brew install for every user.
Add set -euo pipefail at the top of this step's run: block so any upstream pipe failure terminates the script immediately.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/bump-homebrew.yml, line 32:
<comment>Without `set -o pipefail`, a `curl` failure (e.g., 404 for a missing tarball) is masked by the pipeline — `shasum` hashes the empty stdin and produces `e3b0c44298fc1c149afbf4c8996fb924...`, which is non-empty, so the `[ -z "$sha" ]` guard on the next line is silently bypassed. The formula would be pushed with a bogus checksum, breaking `brew install` for every user.
Add `set -euo pipefail` at the top of this step's `run:` block so any upstream pipe failure terminates the script immediately.</comment>
<file context>
@@ -0,0 +1,105 @@
+ for target in darwin-arm64 darwin-x64 linux-x64; do
+ url="https://github.com/superset-sh/superset/releases/download/${TAG}/superset-${target}.tar.gz"
+ echo "Fetching SHA for $url"
+ sha=$(curl -fsSL "$url" | shasum -a 256 | awk '{print $1}')
+ if [ -z "$sha" ]; then
+ echo "::error::Failed to compute SHA for $target"
</file context>
| TAG="${{ github.event.release.tag_name }}" | ||
| VERSION="${TAG#cli-v}" | ||
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | ||
| echo "tag=$TAG" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Compute SHA256 for each tarball |
There was a problem hiding this comment.
P1: ${{ github.event.release.tag_name }} is interpolated directly into the shell script by the Actions runner before the shell parses it. A tag name with shell metacharacters (backticks, $(...), etc.) could execute arbitrary code. Pass it through an env: block instead, matching the pattern already used in the shas step below.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/bump-homebrew.yml, line 19:
<comment>`${{ github.event.release.tag_name }}` is interpolated directly into the shell script by the Actions runner before the shell parses it. A tag name with shell metacharacters (backticks, `$(...)`, etc.) could execute arbitrary code. Pass it through an `env:` block instead, matching the pattern already used in the `shas` step below.</comment>
<file context>
@@ -0,0 +1,105 @@
+ - name: Extract version from tag
+ id: version
+ run: |
+ TAG="${{ github.event.release.tag_name }}"
+ VERSION="${TAG#cli-v}"
+ echo "version=$VERSION" >> "$GITHUB_OUTPUT"
</file context>
| TAG="${{ github.event.release.tag_name }}" | |
| VERSION="${TAG#cli-v}" | |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | |
| echo "tag=$TAG" >> "$GITHUB_OUTPUT" | |
| - name: Compute SHA256 for each tarball | |
| - name: Extract version from tag | |
| id: version | |
| env: | |
| TAG: ${{ github.event.release.tag_name }} | |
| run: | | |
| VERSION="${TAG#cli-v}" | |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | |
| echo "tag=$TAG" >> "$GITHUB_OUTPUT" |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/marketing/public/cli/install.sh`:
- Around line 60-67: The download_tarball function is emitting the info log to
stdout which contaminates the command-substitution result; change the info
logging in download_tarball so it writes to stderr (e.g., have info stdout
redirected to stderr or call a variant that logs to >&2) while keeping the final
echo "$tmp" on stdout, and ensure the error path also logs to stderr (error
messages already should go to stderr) so that the command substitution capturing
the tarball path (tarball="$(download_tarball ... )") receives only the file
path.
- Line 137: Don't silently ignore chmod failures on the expected binaries;
instead check for the presence and executability of "$INSTALL_DIR/bin/superset"
and "$INSTALL_DIR/bin/superset-host" before or after trying to set permissions
(the current chmod line with 2>/dev/null || true hides real problems). Update
the install script to test -f or -x those paths (using INSTALL_DIR and the
"$INSTALL_DIR/bin/..." names) and if either is missing or not made executable,
emit an error message and exit non‑zero so the installer doesn't print
"Installed!" on a broken extraction; only run chmod when the files exist and
verify chmod succeeded.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: e71ed5ca-3620-470e-93e5-ba14a572e465
📒 Files selected for processing (3)
.github/workflows/bump-homebrew.ymlapps/marketing/public/cli/install.shpackages/cli/scripts/build-dist.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- .github/workflows/bump-homebrew.yml
There was a problem hiding this comment.
2 issues found across 3 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/marketing/public/cli/install.sh">
<violation number="1" location="apps/marketing/public/cli/install.sh:60">
P1: `info` writes to stdout, but `download_tarball` is invoked via command substitution (`tarball="$(download_tarball ...)"`) on line 135, so the log line gets captured into `$tarball` along with the temp path. This corrupts the filename and causes `tar -xzf` to fail every time. Redirect `info` to stderr here: `info "Downloading $url" >&2`.</violation>
<violation number="2" location="apps/marketing/public/cli/install.sh:137">
P2: Do not swallow `chmod` failures; this can produce a false “Installed!” result when binaries are missing or not executable.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
info() wrote to stdout, corrupting command substitution in tarball="$(download_tarball ...)". Redirect both info and warn to stderr. Replace silent `chmod ... || true` with an executable verification loop so a broken tarball fails loudly.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/marketing/public/cli/install.sh`:
- Around line 139-143: The loop that checks each binary currently uses only the
`-x` test (in the for loop over `bin` using the `path` variable), which can be
true for directories; update the condition so it requires both a regular file
and executable permission by checking both `-f` and `-x` for `"$path"` before
calling `error`; modify the `if [ ! -x "$path" ]; then` branch to fail when
either check is missing (i.e., ensure `"$path"` is a regular file and is
executable) and keep using the existing `error` function for reporting.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 1a7b04b0-1ca2-48c7-8029-d9824c9411f8
📒 Files selected for processing (1)
apps/marketing/public/cli/install.sh
* ci: auto-bump Homebrew formula on CLI release When a cli-v* tag is published as a GitHub Release: 1. Compute SHA256 for each platform tarball 2. Rewrite Formula/superset.rb with the new version and SHAs 3. Push to superset-sh/homebrew-tap Requires a HOMEBREW_TAP_TOKEN secret (GitHub PAT with repo access to superset-sh/homebrew-tap). * feat: add install script at superset.sh/cli/install.sh One-liner install for the CLI distribution: curl -fsSL https://superset.sh/cli/install.sh | sh - Detects platform/arch (macOS arm64/x64, Linux x64) - Downloads latest release tarball from GitHub - Extracts to ~/superset/ (or $SUPERSET_HOME) - Adds ~/superset/bin to PATH in the user's shell profile - Respects SUPERSET_VERSION for pinned installs Also: tarball no longer has a top-level superset-<target>/ wrapper, so `tar -xzf ... -C ~/superset` drops contents directly. * fix: address PR review findings on bump-homebrew workflow - Add set -euo pipefail to all run blocks - Curl to tempfile + check exit status instead of piping to shasum (pipes without pipefail mask curl failures and produce the empty-input SHA256) - Inject tag via env: instead of direct ${{ }} interpolation to prevent script injection via malicious tag names. Validate tag format with regex before use. - Render formula via python3 reading from env, eliminating YAML+shell heredoc indentation pitfalls - Add concurrency group to serialize concurrent release publishes - Retry push once with rebase as belt-and-suspenders * fix: redirect install.sh info/warn to stderr and verify binaries info() wrote to stdout, corrupting command substitution in tarball="$(download_tarball ...)". Redirect both info and warn to stderr. Replace silent `chmod ... || true` with an executable verification loop so a broken tarball fails loudly. * fix: require regular file in install.sh binary check
Summary
Adds a GitHub Actions workflow that auto-updates the `superset-sh/homebrew-tap` repository whenever a CLI release is published.
Flow:
After that, users can install via:
```bash
brew install superset-sh/tap/superset
```
Setup required before this lands
Test plan
Depends on
Summary by cubic
Automates Homebrew formula bumps on CLI releases and adds a one-line installer. Improves reliability with stricter workflows and fixes installer output handling and binary verification.
New Features
release.publishedforcli-v*: compute SHA256 fordarwin-arm64,darwin-x64,linux-x64, updateFormula/superset.rb, push tosuperset-sh/homebrew-tap.~/supersetor$SUPERSET_HOME, updates PATH, supportsSUPERSET_VERSION.Bug Fixes
python3, concurrency group, and push retry with rebase.Written for commit 6b1340f. Summary will update on new commits.
Summary by CodeRabbit
New Features
Chores