Skip to content

chore: release stable by default, publish betas on demand - #216

Merged
derrickmehaffy merged 1 commit into
mainfrom
chore/stable-releases-manual-betas
Aug 14, 2026
Merged

chore: release stable by default, publish betas on demand#216
derrickmehaffy merged 1 commit into
mainfrom
chore/stable-releases-manual-betas

Conversation

@derrickmehaffy

Copy link
Copy Markdown
Contributor

Inverts the release model, and fixes the bug that made me hand-create the
v5.1.0-beta draft.

Betas become manual

release-please was configured with prerelease versioning, so every release
it proposed was a beta, and the repo could not reach a stable version without a
Release-As: override. Betas are occasional and deliberate; stable is the
normal case.

Now: release-please proposes stable versions only. A beta is a dispatch of
publish.yml:

  • mode: next
  • version: 5.2.0-beta.0
  • target_branch: defaults to main

It stamps that version across all three packages and publishes to next via
npm-prerelease. Publishing stays inside publish.yml because npm's trusted
publishing validates the workflow filename — a second publishing workflow
could not authenticate.

version must carry a prerelease suffix; stamp-version.mjs refuses a stable
one, so no dispatch can put a stable version on npm. Those come only from
release-please and what is committed to package.json. A release event never
stamps — it publishes the version release-please already wrote and tagged.

The real cause of the manual draft

separate-pull-requests: false. From manifest.js:83:

this.separatePullRequests = manifestOptions?.separatePullRequests
  ?? (Object.keys(repositoryConfig).length === 1);

It defaults to true for a single package. Forcing it false kept the merge
plugin
active, and merge.js:81 hardcodes the branch to
BranchName.ofTargetBranch(targetBranch)no component — while the
strategy's getBranchComponent() still returned monorepo. buildRelease
compares those two and aborted:

✔ Pull request contains releases, but not for component:
⚠ There are untagged, merged release PRs outstanding - aborting

It made sense with three packages. With one it is actively harmful. Removed.

Dry run confirms the branch now carries the component, so the comparison
matches — and the bare title is fixed as a side effect:

component:                                                        (empty → componentless body)
branch:  release-please--branches--…--components--monorepo        (component present)
title:   chore: release 5.1.0-beta.1                              (${version} interpolates)

Verified

The plan step run directly over every mode:

case result
release, stable mode=latest dist_tag=latest
release, prerelease mode=next dist_tag=next (no stamping)
dispatch next + version stamp_version=5.2.0-beta.0 ref=main
dispatch next, no version refused
dispatch next, 5.2.0 refused
dispatch experimental + branch / + sha correct ref
dispatch latest mode=latest, no ref
../evil and --upload-pack=x branches rejected

And the stamper directly: SHA path, explicit prerelease path, and a stable
VERSION refused.

After this merges

The next release PR should read chore: release 5.1.0 and, when merged,
release-please should create the draft by itself — that is the thing to
watch, since it is what failed before.

Release-As: 5.1.0

release-please was configured with prerelease versioning, so every release it
proposed was a beta and the repository could not reach a stable version without
a Release-As override. Betas are occasional and deliberate; stable releases are
the normal case. This inverts that.

release-please now proposes stable versions only. A beta is a manual dispatch
of publish.yml with mode=next and an explicit version, stamped across the three
packages and published to the `next` dist-tag. Publishing stays in publish.yml
because npm's trusted publishing validates the workflow filename, so a second
publishing workflow could not authenticate.

stamp-experimental-version.mjs becomes stamp-version.mjs and takes either a SHA
(experimental) or an explicit VERSION. VERSION must carry a prerelease suffix,
so a dispatch cannot fabricate a stable version - those come only from
release-please and what is committed to package.json. A `release` event never
stamps: it publishes the version release-please already wrote and tagged.

Also removes `separate-pull-requests: false`, which was the real reason
github-release refused to create the 5.1.0-beta draft and it had to be made by
hand. manifest.js defaults it to true for a single package; forcing it false
kept the merge plugin active, and merge.js hardcodes the branch to
BranchName.ofTargetBranch - no component - while the strategy's
getBranchComponent() still returned "monorepo". buildRelease compares those two
and aborted on the mismatch. With it removed the strategy names its own branch,
the components match, and the release is created automatically. It also fixes
the bare "chore: release main" title, which now reads "chore: release 5.1.0".

Verified by running the plan step directly over every mode: release/stable ->
latest, release/prerelease -> next, dispatch+version -> stamped next, dispatch
without a version and with a stable version both refused, experimental by
branch and by sha, and two hostile branch names rejected.

Co-Authored-By: Claude <noreply@anthropic.com>
@derrickmehaffy
derrickmehaffy merged commit 08c6092 into main Aug 14, 2026
12 checks passed
This was referenced Aug 14, 2026
derrickmehaffy added a commit that referenced this pull request Aug 14, 2026
The last release was 5.1.0-beta and release-please does not graduate on its
own: the default versioning strategy keeps the prerelease suffix, so the open
release PR proposed 5.1.1-beta rather than 5.1.0.

Release-As applies to a single release and leaves nothing in the config, unlike
the "release-as" config key which would pin every subsequent release.

The footer was in #216's pull request body and did not survive. GitHub only
builds a squash commit from the title and body when the branch has more than
one commit; with a single commit it uses that commit's message. It is recorded
in the release skill so the next person does not lose an hour to it.

Release-As: 5.1.0
@derrickmehaffy
derrickmehaffy deleted the chore/stable-releases-manual-betas branch August 14, 2026 05:46
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