You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Title release PRs with a rocket prefix, add the release label, and detect releases by commit marker - #16551
New feature (non-breaking change which adds functionality)
Automation (AI changes or Github Actions to reduce effort of manual tasks)
Why
Release PRs opened by the prepare-release bot are titled like RELEASE: Releasing 10 package(s) (0.85-stable) (for example #16504). They are hard to
pick out from other PRs and carry no label to filter on. Dependabot PRs already use
short emoji prefixes such as 📦 [main] (#16548); this gives release PRs the same
treatment.
CI decides whether a merged commit is a release by its first line (RELEASE:). GitHub
uses the PR title as that line when a PR has more than one commit (for example #16248,
which had a lock-file fix on top) or when the merger edits it. With the new title, such
a release would silently build as a developer build: no publish, no tag. So this PR
also moves release detection to a marker in the commit body, which survives squash
merges.
Backports: #16557 (0.85-stable) and #16558 (0.81-stable). Until they merge, those
branches keep the old RELEASE: detection, while a manual bot run from main that
targets them would already use the new title. Merge them together with this PR.
What
New release PR title.🚀 [<branch>]: Release N packages (1 package when there
is only one). The branch drops one trailing -stable: [main], [0.85], [0.81].
release label. Added on create (gh pr create --label) and on every refresh
(gh pr edit --add-label); other labels are kept. The label must exist in the repo.
Commit marker. The bot's commit keeps the subject RELEASE: Releasing N package(s) (<branch>) and gains the body line RNW-Release-Branch: <branch>.
CI release detection (.ado/scripts/detectReleaseBuild.js, no dependencies).
Setup reads the full message of the built commit:
exactly one well-formed marker naming the built branch means a release;
a malformed, duplicate or wrong-branch marker fails Setup visibly (in auto mode);
with no marker, the old RELEASE: first-line rule applies and the log says so;
PR builds keep the prepare-release/ branch rule; the isReleaseBuild
auto/true/false parameter still overrides.
Source tag step now also requires a release commit, so forcing isReleaseBuild=false never tags. The release pipeline is unchanged.
Dry run prints the title, label and full commit message.
Tests use Node's built-in runner (node:test); no new dependencies. The package
entry point is now an exported main() that bin.js calls; exit codes are unchanged.
Screenshots
N/A
Testing
Unit tests for the title, gh commands, create/refresh/dry-run/bump-only flows, and
the detector (CRLF/LF, long and squash bodies, co-author trailers, rewritten
subjects, malformed/duplicate/wrong-branch markers, legacy subject, overrides, PR
builds, pipeline wiring).
Local dry runs on main, 0.85-stable and 0.81-stable show the new title, label and
marker.
Live runs from a test branch:
Prepare-release bot with target 0.85-stable and 0.81-stable updated 🚀 [0.85]: Release 10 packages #16504 and 🚀 [0.81]: Release 13 packages #16545: titles 🚀 [0.85]: Release 10 packages and 🚀 [0.81]: Release 13 packages,
label release, and each commit gained its RNW-Release-Branch: <branch> line.
CI, ordinary commit, true: the tag step was skipped with Expanded: and(True, eq('True', 'True'), eq('False', 'True')), so the Setup result
reaches the NuGet job.
Changelog
Should this change be included in the release notes: no
Release PRs created by the prepare-release bot are titled 🚀 [<branch>]: Release N packages and labeled release; CI detects releases by a commit-body marker.
The prepare-release bot now titles release PRs '🚀 [<branch alias>]: Release N packages' (alias drops one trailing '-stable') and adds the 'release' label on create and refresh without touching other labels. The commit subject still starts with 'RELEASE:'. Dry run prints the title and label. --bump-only is unchanged. Adds unit tests for the package using the built-in Node.js test runner (node:test), with no new dependencies.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
The test does not cover a PR created despite a failed gh response, so it does not verify that a retry updates the existing PR instead of attempting another creation.
The prepare-release bot now adds a release-branch marker line to the body of
its RELEASE: commit. CI reads the full commit message of the built commit with
the new .ado/scripts/detectReleaseBuild.js: a single well-formed marker that
names the built branch makes it a release build; a malformed, duplicate, or
mismatched marker fails Setup in auto mode. Commits without a marker still use
the RELEASE: first-line rule. PR builds keep the prepare-release/ branch rule,
and the isReleaseBuild parameter still forces either scenario.
The source tag step now also requires IsReleaseBuild=True and a release commit,
so forcing a developer build no longer tags. The release pipeline is unchanged.
Adds node:test coverage for the detector and wires it into the root test script.
Vladimir Morozov (vmoroz)
changed the title
Title release PRs with a rocket prefix and add the release label
Title release PRs with a rocket prefix, add the release label, and detect releases by commit marker
Nov 1, 2026
[P1] Both 0.81-stable and 0.85-stable still detect releases and tag sources using the RELEASE: subject prefix. If the bot targets either branch and the squash merge uses this new PR title, its CI ignores the body marker and runs a developer build without publishing or tagging. Backport the detector and tag changes before emitting the new title for those branches, or retain the legacy title until each target is upgraded.
- Read the `RNW-Release-Branch` marker only from the commit body, so a
commit whose subject is the marker line is not treated as a release.
- Test that a rerun refreshes a PR that GitHub created before `gh` failed,
instead of creating a second one.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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
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.
Description
Type of Change
Why
Release PRs opened by the prepare-release bot are titled like
RELEASE: Releasing 10 package(s) (0.85-stable)(for example #16504). They are hard topick out from other PRs and carry no label to filter on. Dependabot PRs already use
short emoji prefixes such as
📦 [main](#16548); this gives release PRs the sametreatment.
CI decides whether a merged commit is a release by its first line (
RELEASE:). GitHubuses the PR title as that line when a PR has more than one commit (for example #16248,
which had a lock-file fix on top) or when the merger edits it. With the new title, such
a release would silently build as a developer build: no publish, no tag. So this PR
also moves release detection to a marker in the commit body, which survives squash
merges.
Backports: #16557 (0.85-stable) and #16558 (0.81-stable). Until they merge, those
branches keep the old
RELEASE:detection, while a manual bot run from main thattargets them would already use the new title. Merge them together with this PR.
What
🚀 [<branch>]: Release N packages(1 packagewhen thereis only one). The branch drops one trailing
-stable:[main],[0.85],[0.81].releaselabel. Added on create (gh pr create --label) and on every refresh(
gh pr edit --add-label); other labels are kept. The label must exist in the repo.RELEASE: Releasing N package(s) (<branch>)and gains the body lineRNW-Release-Branch: <branch>..ado/scripts/detectReleaseBuild.js, no dependencies).Setup reads the full message of the built commit:
RELEASE:first-line rule applies and the log says so;prepare-release/branch rule; theisReleaseBuildauto/true/false parameter still overrides.
isReleaseBuild=falsenever tags. The release pipeline is unchanged.node:test); no new dependencies. The packageentry point is now an exported
main()thatbin.jscalls; exit codes are unchanged.Screenshots
N/A
Testing
ghcommands, create/refresh/dry-run/bump-only flows, andthe detector (CRLF/LF, long and squash bodies, co-author trailers, rewritten
subjects, malformed/duplicate/wrong-branch markers, legacy subject, overrides, PR
builds, pipeline wiring).
marker.
0.85-stableand0.81-stableupdated 🚀 [0.85]: Release 10 packages #16504 and🚀 [0.81]: Release 13 packages #16545: titles
🚀 [0.85]: Release 10 packagesand🚀 [0.81]: Release 13 packages,label
release, and each commit gained itsRNW-Release-Branch: <branch>line.auto:RESULT: isReleaseBuild=False; isReleaseCommit=False.auto: Setup failed withInvalid release marker.false:RESULT: isReleaseBuild=False; isReleaseCommit=True.true: the tag step was skipped withExpanded: and(True, eq('True', 'True'), eq('False', 'True')), so the Setup resultreaches the NuGet job.
Changelog
Should this change be included in the release notes: no
Release PRs created by the prepare-release bot are titled
🚀 [<branch>]: Release N packagesand labeledrelease; CI detects releases by a commit-body marker.