ci: guard production releases to main, harden the itinerary step - #1662
Conversation
Three fixes found while porting this workflow to e2b-dev/code-interpreter. `release.yml` is dispatch-only and `workflow_dispatch` offers every branch in the picker, so a feature branch carrying changesets could publish real packages to npm and PyPI and push the version bump to itself. Preflight now fails fast off `main`; candidates cut from a branch already have release-candidate.yml. The itinerary step could block a release. It only feeds the Slack messages, but a `changeset status` hiccup — or a typo in a future edit to an inline `node -e` block, which no YAML validation catches — failed preflight and stopped the release. It is now `continue-on-error` with a placeholder fallback in the messages, and the transform moved to `.github/scripts/` next to `is_release.sh`, where it can be run against fixture JSON. A package missing from the label map now appears under its workspace name instead of being dropped by `order.filter`. `report-failure` did not list `preflight`, so whether a broken preflight pinged the release channel rested on `failure()` looking past the job's direct dependencies, which is not documented either way. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
PR SummaryLow Risk Overview The Slack itinerary step ran inline in YAML and could fail preflight on
Reviewed by Cursor Bugbot for commit 2c5403b. Bugbot is set up for automated code reviews on this repo. Configure here. |
|
Package ArtifactsBuilt from ef1b411. Download artifacts from this workflow run. JS SDK ( npm install ./e2b-2.38.4-ci-guard-release-ref-and-itinerary.0.tgzCLI ( npm install ./e2b-cli-2.16.2-ci-guard-release-ref-and-itinerary.0.tgzPython SDK ( pip install ./e2b-2.38.0+ci.guard.release.ref.and.itinerary-py3-none-any.whl |
There was a problem hiding this comment.
LGTM — small, well-verified CI hardening change with no application code touched.
What was reviewed: the extracted build_release_itinerary.cjs script (verified its output matches the original inline transform for known packages, and correctly promotes previously-dropped unlabeled packages instead of silently omitting them); the main-branch guard placement and its interaction with continue-on-error/job-level failure semantics; the report-failure needs/failure() wiring; confirmed the script passes the repo's prettier check.
Extended reasoning...
Overview
This PR touches only .github/workflows/release.yml and a new helper script .github/scripts/build_release_itinerary.cjs. It adds a preflight guard that fails the release workflow unless triggered on main, makes the Slack itinerary-building step continue-on-error with a placeholder fallback, extracts the itinerary transform from inline YAML into a testable script, and adds preflight to report-failure's needs so preflight failures reliably trigger the failure notification.
Security risks
No auth, crypto, or data-handling logic is touched. If anything, the main change (guarding workflow_dispatch against non-main refs) reduces risk by preventing an accidental publish of real packages from a feature branch. The only theoretical downside — that a rejected wrong-branch dispatch will now also page #monitoring-releases via report-failure — was already raised and investigated by the bug-hunting pass and reasonably concluded to be intended/benign rather than a bug.
Level of scrutiny
This warrants light scrutiny: it's a CI-only workflow change with no impact on runtime/application code, and the repo has a single blanket CODEOWNER with no special CI ownership. I independently verified the extracted script's behavior against the original inline node -e logic using fixture data (known packages, an unlabeled package, and the empty case) and confirmed the output matches what the PR description claims, including the fix for previously-dropped unlabeled packages. I also confirmed release.yml is not invoked via workflow_call elsewhere, so the new ref guard cannot break any other workflow, and that release-candidate.yml (the referenced alternate path for branch-based candidates) does exist.
Other factors
The bug-hunting pass found no bugs, and the one candidate issue it raised (report-failure paging on benign wrong-branch guard rejections) was examined and ruled out as intentional. No outstanding review comments require action — only bot summaries (Cursor, changeset-bot) are present, and no changeset is needed for a CI-only change.
Three fixes found while porting this workflow to
e2b-dev/code-interpreter(#327).release.ymlcan be dispatched from any branch. It is dispatch-only andworkflow_dispatchoffers every branch in the picker, so a feature branch carrying changesets would publish real packages to npm and PyPI and push the version bump to itself.preflightnow fails fast unless the run is onmain; candidates cut from a branch already go throughrelease-candidate.yml.The itinerary step can block a release. It only feeds the Slack messages, but a
changeset statushiccup — or a typo in a future edit to that inlinenode -eblock, which no YAML validation catches — failspreflightand stops the release. It is nowcontinue-on-errorwith a placeholder fallback in both messages, and the transform moved to.github/scripts/build_release_itinerary.cjsnext tois_release.sh, where it can be run against fixture JSON. A package missing from the label map now shows under its workspace name instead of being dropped byorder.filter, so a fourth publishable package would not silently vanish from the notification.report-failuredid not listpreflight, so whether a broken preflight pings#monitoring-releasesrested onfailure()looking past the job's direct dependencies — not documented either way, so the job now depends on it explicitly.Verified: the extracted script reproduces the current output exactly for
e2b/@e2b/python-sdk/@e2b/cli, in the same order, and handles the empty and unlabeled-package cases; workflow validated against the Actions schema; the script matches the repo's prettier config.🤖 Generated with Claude Code