Refactor release workflow to decouple versioning from publishing - #404
Merged
Conversation
The release workflow ran everything in a single job bound to the "main" environment, so opening the "Version Packages" pull request — and any push to main that had nothing to release — queued up a deployment approval. Split it in two: - A "Version" job with no environment, running changesets/action without a publish-script so it can only ever open/update the pull request. It runs on ubuntu-latest and skips the Android/Rust/cpp toolchain setup, none of which versioning needs. - A "Publish" job that keeps `environment: main` and the full toolchain, and only runs when there are no pending changesets and the registry is actually missing one of our package versions. The registry check is a new `unpublished-packages` script: it asks the same question `changeset publish` asks, so chores, docs and CI commits no longer leave a deployment waiting for approval on a no-op publish. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016jd2RhdRGxJ76QtBGnFTFJ
Replaces the hand-rolled registry check from the previous commit with
`changesets/action/select-mode`, which the action's README points to for
repos on trusted publishing ("it's recommended to set up the individual
sub-actions instead to tighten publish permissions").
select-mode answers 'version', 'publish' or 'none' — internally by way of
`changeset publish-plan`, new in the Changesets v3 we just moved to. That is
exactly the signal scripts/unpublished-packages.ts was computing by hand, so
the script and its package.json entry are gone. The sub-action also gets the
edge cases right: changesets that release nothing report 'none' rather than
'version', and packages needing only a git tag are part of the plan.
Because publish-plan reaches the registry through `pnpm info`, the select
step needs the same npm_config_force escape hatch as publishing. It stays
step-scoped rather than workflow-scoped: as workflow env it would also reach
`pnpm install`, where force means "recreate the lockfile".
Also drops the workflow-level concurrency group. A publish waiting for its
deployment approval used to hold that group, so no later push could refresh
the version pull request until someone approved — the same class of blockage
this change is meant to remove. The version and publish jobs carry their own
groups instead, so they serialise against themselves but not each other.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016jd2RhdRGxJ76QtBGnFTFJ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Restructures the release workflow to separate the "decide what to do" phase from the "do it" phase, eliminating unnecessary deployment approvals for non-release commits and preventing version PRs from being blocked by pending publish approvals.
Key Changes
modejob that determines whether to version, publish, or skip; aversionjob that creates the "Version Packages" PR; and apublishjob that publishes to NPMversionandpublishjobs only run when their respective modes are selected, avoiding unnecessary deployment approvals for chore/docs/CI commitsversionjob:contents: writeandpull-requests: write(no environment required)publishjob:contents: writeandid-token: write(requiresmainenvironment approval)npm_config_force: trueto the publish step only, with a comment explaining why it shouldn't be workflow-levelchangesets/action@v2to the splitchangesets/action/select-mode@v2,changesets/action/version@v2, andchangesets/action/publish@v2Implementation Details
The workflow now uses changesets' split actions to answer "what should happen?" before doing it. This allows:
mainenvironment approvalhttps://claude.ai/code/session_016jd2RhdRGxJ76QtBGnFTFJ