chore: add tag-based release flow for v1.3.0 - #27
Conversation
📝 WalkthroughWalkthroughThe publish workflow triggered automatically on main branch changes has been removed and replaced with a tag-based release workflow. The new workflow publishes to npm and GitHub when version tags are pushed, validates tag matches package.json, and additionally publishes a Homebrew formula to an external tap repository. Documentation and version have been updated accordingly. Changes
Sequence DiagramsequenceDiagram
participant Developer
participant GitHub as GitHub
participant BuildEnv as Build Environment
participant NPMRegistry as NPM Registry
participant GitHubAPI as GitHub API
participant HomebrewTap as Homebrew Tap Repo
Developer->>GitHub: Push version tag (v*)
GitHub->>BuildEnv: Trigger workflow_dispatch
BuildEnv->>BuildEnv: Resolve release tag from ref
BuildEnv->>GitHub: Checkout repo at tag
BuildEnv->>BuildEnv: Setup Node.js 20 + dependencies
BuildEnv->>BuildEnv: npm ci, npm run build
BuildEnv->>BuildEnv: npm run test:run, npm run lint
BuildEnv->>BuildEnv: Validate tag vs package.json version
alt Validation Failed
BuildEnv->>Developer: ❌ Job fails
else Validation Passed
BuildEnv->>NPMRegistry: npm publish --access public
BuildEnv->>GitHubAPI: Create GitHub Release with notes
BuildEnv->>BuildEnv: Download source tarball, compute SHA256
BuildEnv->>BuildEnv: Generate Homebrew formula
BuildEnv->>HomebrewTap: Clone tap, commit & push formula
GitHubAPI->>Developer: ✅ Release created
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 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 |
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/release.yml:
- Around line 67-70: Add an early fast-fail gate that checks for required
secrets (at least HOMEBREW_TAP_GITHUB_TOKEN and NPM_TOKEN) before the
irreversible "Publish to npm" step so the workflow fails before any publish
occurs; implement this by inserting a pre-publish step (e.g., "Validate required
secrets" or "Check secrets") that inspects process.env or GitHub secrets and
exits non‑zero if any required secret is missing, and ensure the existing
"Publish to npm" step (name: "Publish to npm") and the later Homebrew update
steps (the Homebrew update block) run only after that validation passes.
- Around line 91-93: The tarball download step uses curl -L which can write an
HTTP error page to release.tar.gz and still succeed; update the curl invocation
that sets TARBALL_URL and writes release.tar.gz to use a failing, verbose form
(e.g., add --fail and --show-error and consider --retry) and ensure the script
checks curl's exit status before computing SHA256 from release.tar.gz so the
checksum step only runs on a successful download; refer to the TARBALL_URL
variable, the curl command that writes release.tar.gz, and the SHA256 checksum
computation to locate where to update.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: cda84b85-2fba-464b-83d3-acebe1ed03ba
📒 Files selected for processing (4)
.github/workflows/publish.yml.github/workflows/release.ymlREADME.mdpackage.json
💤 Files with no reviewable changes (1)
- .github/workflows/publish.yml
| - name: Publish to npm | ||
| run: npm publish --access public | ||
| env: | ||
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} |
There was a problem hiding this comment.
Fail fast on required secrets before irreversible publish.
With Line 67 publishing to npm before Line 117 Homebrew update, a missing HOMEBREW_TAP_GITHUB_TOKEN will fail late and leave a partial release (published npm package + failed workflow). Add an early required-secrets gate before publish/release steps.
Suggested hardening patch
- name: Verify tag matches package version
id: version_check
run: |
@@
if [ "$ACTUAL_TAG" != "$EXPECTED_TAG" ]; then
echo "Tag mismatch: expected $EXPECTED_TAG, got $ACTUAL_TAG" >&2
exit 1
fi
+
+ - name: Validate required release secrets
+ run: |
+ missing=0
+ if [ -z "${{ secrets.NPM_TOKEN }}" ]; then
+ echo "Missing required secret: NPM_TOKEN" >&2
+ missing=1
+ fi
+ if [ -z "${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}" ]; then
+ echo "Missing required secret: HOMEBREW_TAP_GITHUB_TOKEN" >&2
+ missing=1
+ fi
+ if [ "$missing" -ne 0 ]; then
+ exit 1
+ fiAlso applies to: 117-134
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/release.yml around lines 67 - 70, Add an early fast-fail
gate that checks for required secrets (at least HOMEBREW_TAP_GITHUB_TOKEN and
NPM_TOKEN) before the irreversible "Publish to npm" step so the workflow fails
before any publish occurs; implement this by inserting a pre-publish step (e.g.,
"Validate required secrets" or "Check secrets") that inspects process.env or
GitHub secrets and exits non‑zero if any required secret is missing, and ensure
the existing "Publish to npm" step (name: "Publish to npm") and the later
Homebrew update steps (the Homebrew update block) run only after that validation
passes.
| TARBALL_URL="https://github.com/${{ github.repository }}/archive/refs/tags/${{ steps.release_tag.outputs.tag }}.tar.gz" | ||
| curl -L "$TARBALL_URL" -o release.tar.gz | ||
| SHA256=$(sha256sum release.tar.gz | awk '{print $1}') |
There was a problem hiding this comment.
Harden tarball download before checksum generation.
Line 92 uses curl -L without --fail; HTTP errors can still produce a file and a checksum, resulting in a broken Homebrew formula.
Suggested robustness patch
- curl -L "$TARBALL_URL" -o release.tar.gz
+ curl -fL --retry 3 --retry-all-errors --retry-delay 2 "$TARBALL_URL" -o release.tar.gz
+ test -s release.tar.gz
SHA256=$(sha256sum release.tar.gz | awk '{print $1}')📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| TARBALL_URL="https://github.com/${{ github.repository }}/archive/refs/tags/${{ steps.release_tag.outputs.tag }}.tar.gz" | |
| curl -L "$TARBALL_URL" -o release.tar.gz | |
| SHA256=$(sha256sum release.tar.gz | awk '{print $1}') | |
| TARBALL_URL="https://github.com/${{ github.repository }}/archive/refs/tags/${{ steps.release_tag.outputs.tag }}.tar.gz" | |
| curl -fL --retry 3 --retry-all-errors --retry-delay 2 "$TARBALL_URL" -o release.tar.gz | |
| test -s release.tar.gz | |
| SHA256=$(sha256sum release.tar.gz | awk '{print $1}') |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/release.yml around lines 91 - 93, The tarball download
step uses curl -L which can write an HTTP error page to release.tar.gz and still
succeed; update the curl invocation that sets TARBALL_URL and writes
release.tar.gz to use a failing, verbose form (e.g., add --fail and --show-error
and consider --retry) and ensure the script checks curl's exit status before
computing SHA256 from release.tar.gz so the checksum step only runs on a
successful download; refer to the TARBALL_URL variable, the curl command that
writes release.tar.gz, and the SHA256 checksum computation to locate where to
update.
There was a problem hiding this comment.
Pull request overview
This PR switches publishing from “push to main” to a tag-driven release flow for v1.3.0, ensuring the pushed tag matches package.json before publishing, and extends the release to update a Homebrew tap.
Changes:
- Add a new tag-triggered GitHub Actions workflow to build/test/lint, publish to npm, create a GitHub release, and update a Homebrew tap formula.
- Remove the prior push-to-main npm publish workflow.
- Bump package version to
1.3.0and update installation docs (npm global + Homebrew).
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| README.md | Updates install instructions to use global npm install and adds Homebrew install steps. |
| package.json | Bumps version to 1.3.0. |
| .github/workflows/release.yml | Implements tag-based release pipeline, GitHub release creation, and Homebrew tap update. |
| .github/workflows/publish.yml | Removes the previous main-branch publish workflow. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| depends_on "node" | ||
|
|
||
| def install | ||
| system "npm", "install", *std_npm_args | ||
| man1.install "man/excalidraw-cli.1" | ||
| end |
There was a problem hiding this comment.
The generated Homebrew formula installs the package from the GitHub source tarball but never builds the TypeScript output. This repo does not include a committed dist/ directory, and the CLI bin points to dist/cli.js, so a Homebrew install from source will be missing the executable output and likely fail at runtime. Consider either (a) updating the formula’s install to run the build step (and ensure any build-time deps are available) before installing, or (b) making the formula pull the npm registry tarball (which includes the built dist/).
| TARBALL_URL="https://github.com/${{ github.repository }}/archive/refs/tags/${{ steps.release_tag.outputs.tag }}.tar.gz" | ||
| curl -L "$TARBALL_URL" -o release.tar.gz | ||
| SHA256=$(sha256sum release.tar.gz | awk '{print $1}') | ||
| echo "tarball_url=$TARBALL_URL" >> "$GITHUB_OUTPUT" | ||
| echo "sha256=$SHA256" >> "$GITHUB_OUTPUT" |
There was a problem hiding this comment.
The SHA256 computation uses curl -L without failing on non-2xx responses. If the tarball URL 404s or GitHub returns an HTML error page, the workflow will still compute a SHA and publish an invalid Homebrew formula. Use curl options that fail on HTTP errors (and optionally validate the downloaded file) so the job stops before updating the tap.
| HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }} | ||
| run: | | ||
| git config --global user.name "github-actions[bot]" | ||
| git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" | ||
|
|
||
| git clone "https://x-access-token:${HOMEBREW_TAP_GITHUB_TOKEN}@github.com/swiftlysingh/homebrew-tap.git" homebrew-tap | ||
| cp Formula/excalidraw-cli.rb homebrew-tap/Formula/excalidraw-cli.rb |
There was a problem hiding this comment.
Cloning the tap repo with the token embedded in the URL can leak the credential in some git/curl error output (even if GitHub attempts to mask it). Prefer a pattern that avoids placing secrets in command-line arguments, e.g., using actions/checkout with repository + token, or configuring git credentials via a credential helper/env so the token isn’t part of the clone URL.
Summary
Validation
Notes
NPM_TOKENexists in the repo secretsHOMEBREW_TAP_GITHUB_TOKENdoes not currently exist in the repo secrets, so taggingv1.3.0now would likely fail during Homebrew tap updateSummary by CodeRabbit
New Features
Documentation
Chores