Skip to content

Bring the release runbook up to date, protect release branches, and fix main's preview version - #568

Draft
ChrisonSimtian wants to merge 4 commits into
Fallout-build:mainfrom
ChrisonSimtian:docs/release-runbook-notes-and-rc-counter
Draft

Bring the release runbook up to date, protect release branches, and fix main's preview version#568
ChrisonSimtian wants to merge 4 commits into
Fallout-build:mainfrom
ChrisonSimtian:docs/release-runbook-notes-and-rc-counter

Conversation

@ChrisonSimtian

@ChrisonSimtian ChrisonSimtian commented Jul 26, 2026

Copy link
Copy Markdown
Collaborator

Brings the release runbook in line with what the project actually ships, and captures the release-branch protection config in the repo. Everything here came out of cutting v10.4.0-rc.4. Docs + one config file; no product code.

1. Release branches are protected by a ruleset

release/v10.4 ran unprotected from its cut on 2026-07-21 until today — anything could be pushed straight to the branch that fires production releases. The on-demand cut (ADR-0007) has no protection step attached, and the runbook's step 3 pointed at scripts/release-branch-protection.json — a file that never existed.

Now a pattern-based ruleset on refs/heads/release/** (19766406), so every release line is protected the moment the branch exists — release/v10.4 now, a release/2027 cut later, with no per-branch step to forget. Mirrors main's profile; repo admins bypass, matching the tag ruleset. Payload committed at .github/release-branch-ruleset.json (in .github/, not scripts/ — it's GitHub config, not tooling) with the PUT command to re-apply after an edit.

2. The runbook described a line that doesn't exist

Every example named release/2026 and v2026.1.X, while the line actually shipping is release/v10.4 at 10.4.0-rc.N — so no command was copy-pasteable. The channel table also claimed previews were 2026.1.0-preview.<height> when main's version.json says 10.0.0-preview.{height}.

Documents release/vMAJOR.MINOR alongside release/YYYY (the pipeline matches both), adds a "lines live right now" block as the one place to keep current, and retargets the examples. ADR-0004/0007 CalVer intent is unchanged — a year cut substitutes branch and tag and works identically.

3. Two traps that cost time on rc.4

  • --ref on a workflow_dispatch selects the workflow definition, not just the source to pack. Dispatching against the default branch runs main's pipeline — which differs from the release branch's whenever a fix isn't forward-ported yet — and still pushes to nuget.org.
  • A green release run is not evidence packages shipped. Every publish job is conditional, so a bad condition skips it while the run reports success. That was true of all three jobs on the dispatch path (fixed in #567). Adds the commands to check what actually ran and whether the version resolves.

4. Prerelease numbers are a manual counter

The rc number is pinned literally in version.json rather than derived from {height}, which would have jumped rc.3rc.23. That makes bumping manual, and forgetting means republishing an existing version — which --skip-duplicate swallows silently.

5. main's preview lane moves onto the 10.4 core

main advertised 10.0.0-preview.{height} while the line actually shipping is 10.4.0 — so the trunk published previews numbered below the branch cut from it. 10.0.0 was never a target anyone intends to release; it was left behind when the 10.4 line was cut. Now 10.4.0-preview.{height}.

Two consequences, both verified:

  • The height resets, so previews restart at 10.4.0-preview.1 rather than continuing from 10.0.0-preview.34. Nothing regresses — 10.4.0 sorts above 10.0.0, so the new previews still supersede every published one.
  • 10.4.0-preview.N sorts below 10.4.0-rc.N, which is right while main is the trunk 10.4.0 stabilises from. Once 10.4.0 goes GA, main needs rolling to the next core (10.5.0, or the CalVer major) or its previews start reading as older than the released package despite carrying newer code — the same roll-forward the yearly-cut runbook already describes.

Ordering checked against SemVer 2.0 precedence: 10.0.0-preview.34 < 10.4.0-preview.1 < 10.4.0-rc.4 < 10.4.0, and 10.3.47 < 10.4.0-preview.1.

Corrections to existing claims

Two things the protection docs asserted that aren't true:

  • Stale approvals are not dismissed on new commits (dismiss_stale_reviews: false).
  • Squash merge is not disabled by repo setting — only plain merge commits are (allow_squash_merge: true). So "rebase only" rests on convention, not enforcement. Worth closing separately if you want it enforced; squashing a promotion would collapse reviewed commits into one opaque commit.

Two runbook gaps found while cutting v10.4.0-rc.4.

Prerelease numbers on a release branch are now a literal value in version.json
rather than {height}, so bumping them is a manual step someone has to remember —
and forgetting means tagging republishes an existing version, which
`--skip-duplicate` swallows silently. Both consequences are written down.

Release notes: always use --generate-notes, and anchor --notes-start-tag on the
last GA tag rather than letting gh default to the most recent one. Defaulting
makes an rc diff against the rc before it, which collapses the notes to whatever
landed in between; anchoring on the last GA shows the full set of changes since
the last real release, which is what someone evaluating an rc needs. rc.4 was
first published with hand-written notes for this reason — the fix was the start
tag, not abandoning generation.

Also records the one real gap in generated notes: cherry-picked promotions get
new SHAs, so GitHub attributes them to the promotion PR rather than the original
ones.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ChrisonSimtian ChrisonSimtian added documentation Improvements or additions to documentation target/vCurrent Targets the current version labels Jul 26, 2026
ChrisonSimtian and others added 2 commits July 27, 2026 01:35
release/v10.4 ran unprotected from its cut on 2026-07-21 until today: the
on-demand cut in ADR-0007 has no protection step attached, and the runbook's
step 3 pointed at scripts/release-branch-protection.json — a file that never
existed. Anything could be pushed straight to the branch that fires production
releases.

Replaced with a pattern-based ruleset on refs/heads/release/**, so every release
line is protected the moment the branch exists — release/v10.4 now, a
release/2027 CalVer cut later — with no per-branch step to forget. It mirrors
main's profile: no deletion, no force-push, linear history, PRs with CODEOWNERS
review and conversation resolution, and the ubuntu-latest check. Repo admins
bypass, matching the tag ruleset.

The payload is committed under .github/ so the config is reviewable in the repo
rather than only in settings, with the PUT command to re-apply it after an edit.

Also corrects two things the protection docs asserted that were not true:
stale approvals are not dismissed on new commits (dismiss_stale_reviews is
false), and squash merge is not disabled by repo setting — only plain merge
commits are, so the no-squash rule on release branches rests on convention.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The runbook described a CalVer production line that does not exist yet. Every
example named release/2026 and v2026.1.X, while the line actually shipping is
release/v10.4 at 10.4.0-rc.N — so none of the commands could be copy-pasted, and
the channel table claimed previews were 2026.1.0-preview.<height> when main's
version.json says 10.0.0-preview.{height}.

Documents the release/vMAJOR.MINOR line shape alongside release/YYYY (the
pipeline recognises both, via publicReleaseRefSpec and validate-ref), adds a
"lines live right now" block as the single place to keep current, and retargets
the examples at the live line. The CalVer intent from ADR-0004/0007 is unchanged
— a year cut substitutes the branch and tag and works identically.

Adds two things learned cutting rc.4 that the runbook did not warn about:

--ref on a workflow_dispatch selects the *workflow definition*, not just the
source to pack. Dispatching against the default branch runs main's copy of the
pipeline, which differs from the release branch's whenever a fix has not been
forward-ported — and still pushes the result to nuget.org.

A green release run is not evidence that packages shipped. Every publish job is
conditional, so a bad condition skips it while the run reports success; that was
true of all three jobs on the dispatch path. Adds the two commands that check
what actually ran and whether the version resolves.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ChrisonSimtian ChrisonSimtian changed the title Document rc numbering and how to generate release notes Bring the release runbook up to date and protect release branches by ruleset Jul 26, 2026
main advertised 10.0.0-preview.{height} while the line actually shipping is
10.4.0 — so the trunk, which is ahead of release/v10.4 in content, published
previews numbered below the branch cut from it. 10.0.0 was never a target
anyone intends to release; it was left behind when the 10.4 line was cut.

Sets the preview core to 10.4.0. Consequences worth knowing:

Changing the version field resets the git height, so previews restart at
10.4.0-preview.1 rather than continuing from 10.0.0-preview.34. Nothing
regresses — the 10.4.0 core sorts above 10.0.0, so the new previews still
supersede every previously published one.

10.4.0-preview.N sorts below 10.4.0-rc.N, which is correct while main is the
trunk that 10.4.0 stabilises from. Once 10.4.0 goes GA, main will need moving to
the next core (10.5.0, or the CalVer major) or its previews will start reading as
older than the released package despite carrying newer code — the same roll-
forward step the yearly-cut runbook already describes.

Docs updated to match: main keeps {height} for previews, only the core changes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ChrisonSimtian ChrisonSimtian changed the title Bring the release runbook up to date and protect release branches by ruleset Bring the release runbook up to date, protect release branches, and fix main's preview version Jul 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation target/vCurrent Targets the current version

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant