Skip to content

ci(build): Add snapshot release workflow#3212

Open
runningcode wants to merge 4 commits intomasterfrom
no/ci-snapshot
Open

ci(build): Add snapshot release workflow#3212
runningcode wants to merge 4 commits intomasterfrom
no/ci-snapshot

Conversation

@runningcode
Copy link
Contributor

@runningcode runningcode commented Mar 12, 2026

Summary

Adds a workflow_dispatch-triggered snapshot release pipeline that reuses the existing build workflow, enabling on-demand pre-release builds from any branch. For now we are only publishing to npm under the snapshot tag.

Background

We want to allow easy snapshot releases to ease internal testing as well as customer testing.

What it does

  • New snapshot.yml workflow: Computes a semver-compliant snapshot version (e.g. 3.4.0-snapshot.20260312.abc1234) by bumping the minor version from Cargo.toml, patches all version files via scripts/bump-version.sh, pushes a temporary snapshot branch, then triggers the build
  • Makes build.yml callable: Adds workflow_call inputs (skip-signing, is-snapshot, checkout-ref) so the snapshot workflow can reuse the full build matrix
  • Skips unnecessary steps for snapshots: macOS code signing/notarization, Python package builds, Docker image builds, and the release merge job are all conditionally skipped
  • Publishes to npm under snapshot tag: Platform-specific binary packages and the main @sentry/cli package are published with --tag snapshot so they don't affect the latest tag
  • Cleans up after itself: The temporary snapshot branch is deleted after publishing (or on failure)

🤖 Generated with Claude Code

Add a workflow_dispatch-triggered snapshot release pipeline that reuses
the existing build workflow. Snapshot builds skip macOS code signing,
override versions with a snapshot identifier, and publish to npm under
the `snapshot` tag.

- Add `workflow_call` inputs to build.yml for `skip-signing` and
  `snapshot-version`
- Add `override-version` composite action to patch Cargo.toml,
  package.json, and npm-binary-distributions
- Add `snapshot.yml` workflow that computes a snapshot version, triggers
  the build, and publishes to npm
- Skip Python, Docker, and merge jobs for snapshot builds

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Instead of patching version files at build time via the override-version
composite action, snapshots now follow the same pattern as releases:
bump all version files upfront using bump-version.sh, commit to a
temporary snapshot branch, and let build.yml build from correct source.

This removes the fragile override-version action (called 5 times across
different jobs with sed/awk/node), replaces the snapshot-version input
with checkout-ref and is-snapshot, and adds a cleanup job to delete the
temporary branch after publish.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
if: always()
runs-on: ubuntu-24.04
steps:
- name: Delete snapshot branch
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

optionally, we can also keep these snapshot branches, but i don't think they will be useful.

@@ -0,0 +1,114 @@
name: Snapshot Release

on:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

manual trigger to test. we can change this to build on every push to master once we know it is working.

with:
node-version: '20.10.0'

- name: Bump versions
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so another way to do this would be to modify the versions in place in the action/workflow using sed and regexes.

this would remove the need to commit and create the snapshot branch somewhere but then we have two different mechanisms to patch the versions which could lead to drift. without modifying in place, there's no way to share the patched repo between workflows.

if-no-files-found: 'error'

platform-specific-docker:
if: ${{ !inputs.is-snapshot }}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

skip docker publishing

@@ -297,11 +327,14 @@ jobs:
if-no-files-found: 'error'

python:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not publishing to pip

@@ -179,6 +199,7 @@ jobs:
name: unsigned-bin-macos-${{ matrix.arch }}

- name: Sign binary
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no signing for snapshots

is-snapshot:
type: boolean
default: false
checkout-ref:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need this checkout-ref to share the version patched repo between workflows. see comment here for more details: https://github.com/getsentry/sentry-cli/pull/3212/changes#r2924915514

@runningcode runningcode marked this pull request as ready for review March 12, 2026 14:27
@runningcode runningcode requested review from a team and szokeasaurusrex as code owners March 12, 2026 14:27
The upload artifact preserves the platform subdirectory structure
(e.g., darwin/, linux-x64/), so after download the tarballs land at
npm-distributions/<platform>/*.tgz, not npm-distributions/*.tgz.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The node job downloads artifact-bin-* which includes macOS artifacts
uploaded by sign-macos-binaries, but didn't declare that dependency.
This could cause the npm package to be built with incomplete checksums
(missing macOS entries). sign-macos-binaries already depends on macos
and macos_universal, so those are covered transitively.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment on lines 221 to 227
--wait \
sentry-cli-Darwin-${{ matrix.arch }}.zip

- name: Upload signed binary
- name: Upload binary
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # 7.0.0
with:
name: artifact-bin-macos-${{ matrix.arch }}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The conditional upload in the sign-macos-binaries job is skipped when skip-signing is true, causing downstream jobs that depend on the macOS artifact to fail.
Severity: CRITICAL

Suggested Fix

Remove the if: ${{ !inputs.skip-signing }} condition from the "Upload binary" step in the sign-macos-binaries job. This will ensure the binary, whether signed or unsigned, is always uploaded and available for downstream jobs.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: .github/workflows/build.yml#L221-L227

Potential issue: In the `sign-macos-binaries` job, the step to upload the binary
artifact is conditional on `if: ${{ !inputs.skip-signing }}`. When the snapshot workflow
runs with `skip-signing: true`, this condition causes the upload step to be skipped.
Consequently, the macOS binary artifact is never created. Downstream jobs, such as
`npm-distributions`, attempt to download this artifact. While the download action
succeeds silently without finding the file, a subsequent `mv` command fails with a "No
such file or directory" error, causing the entire snapshot release workflow to fail.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

env:
GH_TOKEN: ${{ github.token }}
run: |
gh api -X DELETE "repos/${{ github.repository }}/git/refs/heads/${{ needs.prepare.outputs.ref }}" || true
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleanup job may call API with empty ref

Low Severity

The cleanup job runs with if: always() and depends on prepare, but if prepare fails before the "Push snapshot branch" step completes, needs.prepare.outputs.ref will be empty. This causes the gh api -X DELETE call to target repos/{repo}/git/refs/heads/ with no ref path. While || true prevents a job failure, it also silently swallows errors from legitimate cleanup attempts (e.g., network failures when the branch really does exist). Adding a condition like needs.prepare.outputs.ref != '' to the step or the job's if would make this more robust and avoid masking real failures.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant