Skip to content

Add automated milestone management with Versions.props detection#34686

Merged
PureWeen merged 25 commits into
mainfrom
feature/milestone-drift-fixer
Apr 16, 2026
Merged

Add automated milestone management with Versions.props detection#34686
PureWeen merged 25 commits into
mainfrom
feature/milestone-drift-fixer

Conversation

@PureWeen
Copy link
Copy Markdown
Member

@PureWeen PureWeen commented Mar 26, 2026

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Summary

Adds automated milestone management for PRs and issues. A single workflow handles both automatic milestoning on PR merge and manual tag-based reconciliation after releases ship.

Problem

When PRs merge, they often get milestoned for the wrong service release or not milestoned at all. The actual release a PR ships in depends on which Candidate PR carries the commits and when the SR branch is cut. This creates milestone drift that makes release queries and notes inaccurate.

Solution

Files

File Purpose
.github/scripts/Fix-MilestoneDrift.ps1 Core engine — version detection, milestone mapping, correction logic
.github/scripts/Fix-MilestoneDrift.Tests.ps1 77 Pester unit tests for all pure functions
.github/workflows/fix-milestone-drift.yml Single workflow with dual triggers (auto on merge + manual dispatch)

How It Works

Version Detection

The source of truth is eng/Versions.props. For single-PR mode, the script reads MajorVersion and PatchVersion at the PR's merge commit SHA to determine what version the branch was building when the PR merged.

Milestone Mapping

Patch Example Milestone Rule
0 10.0.0 .NET 10.0 GA Exact zero
1-9 10.0.5 .NET 10.0 SR1 Early patches
N0 10.0.60 .NET 10 SR6 patch / 10
N0+x 10.0.41 .NET 10 SR4.1 Sub-patch = distinct milestone

Sub-patches are distinct — .NET 10 SR4.1 != .NET 10 SR4. Script warns and skips gracefully if the milestone doesn't exist on GitHub yet.

Milestone Normalization

GitHub milestones have inconsistent naming (.NET 10.0 SR4 vs .NET 10 SR4, .NET 10.0 GA vs .NET 10 GA). The script normalizes both SR and GA forms as equivalent.

Branch Ownership Detection

Reads <MajorVersion> from eng/Versions.props on origin/main. No hardcoded version numbers — automatically handles version transitions when main moves from .NET 10 to .NET 11.

Merge-Up Protection

Checks each PR's base.ref to skip PRs from different .NET versions (prevents merge-up commits from causing incorrect milestoning):

base.ref MainBranch=main MainBranch=net11.0
main
inflight/*, darc/*
net11.0
release/10.*
release/11.*

Linked Issue Detection

Scans PR title and body for:

  • fix/fixes/fixed/close/closes/closed/resolve/resolves/resolved #N
  • Same keywords + https://github.com/dotnet/maui/issues/N

Bare informational URLs are ignored. Results are deduplicated.


Single Workflow, Two Triggers

Auto: On PR Merge (pull_request_target)

Triggers on every PR merge to main, net*.0, inflight/*, or release/*. Reads Versions.props at the merge commit, sets the milestone on the PR and its linked issues. If the milestone doesn't exist yet on GitHub, warns and skips gracefully (no red CI).

Manual: Tag Reconciliation (workflow_dispatch)

Input Type Default Description
pr_number string (empty) Single PR to check
tag string (empty) Release tag to audit (e.g. 10.0.60)
apply boolean false Apply changes (default: dry-run)
create_issue boolean false Create GitHub issue with report

Safety

Rule Purpose
Dry-run by default (manual) workflow_dispatch requires explicit apply checkbox
Date cutoff (2026-01-01) Never touches PRs merged before 2026
Branch check Skips merge-up PRs from different .NET versions
Deduplication Same issue corrected once even if linked from multiple PRs
Fixing-keyword URLs Bare informational issue references ignored
Milestone must exist Warns and skips gracefully if milestone not found
Merge commit fetch Fetches commit on demand for PRs merged to inflight
Warning diagnostics Silent failures in version detection log warnings
GA tag support Tag mode handles first release tag (no previous tag)
Input sanitization Workflow inputs flow through env: vars, not inline interpolation
Error propagation Invoke-ApplyCorrections throws on failure; CI goes red
Zero-check guard Tag mode throws when all PRs fail to fetch (prevents false "all correct")

Known Limitations

  • Preview/RC milestones: The script currently maps PatchVersion=0 to .NET X.0 GA. It does not read PreReleaseVersionLabel or PreReleaseVersionIteration from Versions.props, so PRs merged to net11.0 during the preview phase will not be automatically milestoned (the workflow gracefully skips with a warning). Preview milestone support is planned as a follow-up.
  • GA tag rate limit: Running -Tag X.0.0 (the very first release tag) in manual mode walks the full git history, which could exhaust GitHub API rate limits on large repos.

Test Suite

77 Pester unit tests covering all pure functions:

Block Tests Coverage
ConvertTo-Milestone 17 GA, SR1-SR10, sub-patches (SR4.1, SR10.1), early patches, preview/invalid
Test-MilestoneMatch 12 Exact, normalization (SR + GA), sub-patch distinction, null/empty
Find-MatchingMilestone 5 Direct, normalized, alternate format, non-existent
Find-PreviousTag 9 Ordered traversal, boundaries, major-version isolation
Get-LinkedIssues 11 Keywords (incl. close/resolve bare), URLs, dedup, case
Get-PatchVersion 4 Valid, GA, large, invalid
Test-IsReleaseTag 5 Valid release, wrong major, preview, invalid
Test-PrBelongsToVersion 14 main/net11.0 contexts, inflight, darc, release, feature

Local Usage

# Dry-run: check a single PR
./Fix-MilestoneDrift.ps1 -PrNumber 34620 -RepoPath . -Verbose

# Dry-run: audit all PRs in a tagged release
./Fix-MilestoneDrift.ps1 -Tag 10.0.50 -RepoPath . -Verbose

# Apply fixes
./Fix-MilestoneDrift.ps1 -PrNumber 34620 -Apply

# Full tag audit + apply + report issue
./Fix-MilestoneDrift.ps1 -Tag 10.0.50 -Apply -CreateIssue

# Run tests
Invoke-Pester ./Fix-MilestoneDrift.Tests.ps1 -Output Detailed

Validated Results

Adds a PowerShell script that detects and fixes incorrectly milestoned PRs
and issues by comparing what shipped in each release tag against the expected
milestone. Supports three modes:
- Single PR: -PrNumber 33818 (auto-detects which release it shipped in)
- Single tag: -Tag 10.0.50 (checks all PRs in that release)
- All SRs: -AllSRs (scans all service releases)

Dry-run by default; -Apply flag required to make changes.

Includes 56 Pester unit tests for milestone mapping, normalization, and
linked issue extraction logic.

GitHub Action workflow supports workflow_dispatch for manual testing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 26, 2026 20:03
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 26, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 34686

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 34686"

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds automation to detect and correct “milestone drift” by mapping merged PRs (and linked issues) to the service release tag they actually shipped in, with an opt-in apply mode via workflow_dispatch.

Changes:

  • Added a Fix-MilestoneDrift.ps1 PowerShell script to analyze PRs/releases using git tags and gh api, and optionally apply milestone updates.
  • Added a fix-milestone-drift.yml workflow to run the script in dry-run (default) or apply mode.
  • Added Fix-MilestoneDrift.Tests.ps1 Pester tests for the script’s pure functions (mapping/matching/parsing).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
.github/workflows/fix-milestone-drift.yml New workflow_dispatch entrypoint to run the drift script with PR/tag/apply inputs.
.github/scripts/Fix-MilestoneDrift.ps1 Core implementation: tag↔milestone mapping, PR enumeration between tags, GitHub milestone/issue updates via gh.
.github/scripts/Fix-MilestoneDrift.Tests.ps1 Pester unit tests for mapping/matching and linked-issue extraction helpers.

Comment thread .github/scripts/Fix-MilestoneDrift.ps1 Outdated
Comment thread .github/scripts/Fix-MilestoneDrift.ps1
Comment thread .github/workflows/fix-milestone-drift.yml Outdated
Comment thread .github/scripts/Fix-MilestoneDrift.ps1 Outdated
Comment thread .github/scripts/Fix-MilestoneDrift.ps1 Outdated
PureWeen and others added 3 commits March 26, 2026 15:10
- Remove -AllSRs parameter entirely (too dangerous for bulk runs)
- Add hard cutoff: PRs merged before 2026-01-01 are always skipped
- Script now only supports -PrNumber (single PR) and -Tag (single release)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
kubaflo and others added 7 commits March 31, 2026 20:57
…tion, injection fix

- Move Set-StrictMode inside dot-source guard so it doesn't leak into
  Pester or other callers when the script is dot-sourced for testing
- Add Get-PrNumbersReachableFromTag to handle GA (first tag) detection
  in Find-TagContainingPr instead of skipping it
- Validate -Tag exists in repo and warn if PR is not in the tag range
  when -Tag is manually provided in single-PR mode
- Replace pwsh -Command string concatenation with pwsh -File and proper
  bash array to prevent argument/command injection via workflow_dispatch

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
ConvertFrom-Json in PowerShell 7 converts ISO 8601 dates to DateTime
objects. Calling [datetime]::Parse() on an already-parsed DateTime
converts it to a locale-dependent string first, which fails on non-US
locales (e.g. '02/13/2026 20:18:56' is not parseable everywhere).

Handle both DateTime and string cases, using InvariantCulture for
string parsing. This fixes 51 silent failures in the 10.0.50 audit.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds a new -CreateIssue switch that creates a GitHub issue in
dotnet/maui with a formatted markdown table of all corrections.
The workflow gets a corresponding create_issue checkbox input.

The issue includes a summary table (PRs checked, corrections needed)
and a full corrections table showing current vs expected milestones.
Only creates the issue when corrections are found.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@PureWeen
Copy link
Copy Markdown
Member Author

PureWeen commented Apr 3, 2026

PR #34686 — Multi-Model Code Review (Round 7 — Final)

CI Status: ⚠️ maui-pr skipped (workflow/script-only PR — expected, no compiled code)


Review Results

Reviewer 1: No issues found.

Reviewer 2: One finding — pre-cutoff PR skips miscounted as errors in tag mode. Previously identified in round 6 and accepted as a follow-up (only affects manual tag-mode against pre-2026 releases; auto-trigger path is unaffected).

Reviewer 3: One finding — missing word boundary in Get-LinkedIssues regex (prefix #123 would match). Previously identified in round 5 and discarded by adversarial consensus (1/3 reviewers; edge case too unlikely in real PR descriptions to warrant regex complexity).

No new findings across any reviewer.


Summary Across All Review Rounds

Round Findings Status
1 11 findings (2 critical, 4 moderate, 5 minor) All fixed
2 Re-review: 6 fixed, 3 partial, 2 accepted Partials fixed in round 3
3 Re-review: all resolved Clean
4 Fresh review: 4 minor All fixed
5 Fresh review: 3 moderate, 1 minor All fixed
6 Fresh review: 2 moderate (GA path), 2 minor Accepted as follow-ups (GA edge case only)
7 No new issues found ✅ Clean

Test Coverage

  • ✅ 77 Pester tests — all pass
  • ✅ Milestone mapping, normalization (including GA), sub-patches, linked issues, branch ownership, close/resolve keywords all tested
  • ✅ Validated against 50+ real PRs with correct results
  • ✅ Auto-trigger path verified: processes exactly 1 PR + linked issues per merge

Recommended Action

Approve — Seven rounds of 3-model review. All actionable findings fixed. No new issues found. Ready to merge.

@PureWeen PureWeen added this to the .NET 10 SR7 milestone Apr 14, 2026
@PureWeen PureWeen changed the title Add milestone drift detection and fix workflow Add milestone drift detection and fix workflow for release tags Apr 14, 2026
github-actions Bot and others added 7 commits April 14, 2026 11:34
- URL pattern now requires fixing keyword (fixes/closes/resolves) before
  GitHub issue URLs, matching GitHub's actual auto-close behavior. Bare
  informational URLs like 'See https://...issues/17549' no longer produce
  false positives.
- Deduplicate corrections by (ItemType, Number) so the same issue linked
  from multiple PRs (e.g. individual PR + Candidate Branch PR) is only
  corrected once.
- Added 2 new tests for URL-only references (58 total, all passing).

Before: 109 corrections (17 duplicates, 1 false positive)
After:  90 corrections (0 duplicates, 0 false positives)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When main (.NET 10) merges into net11.0, all .NET 10 PR commit messages
become reachable from .NET 11 tags. Without protection, running this
script against .NET 11 tags would incorrectly re-milestone thousands
of .NET 10 PRs.

Fix: Check each PR's base.ref (merge target branch) and skip PRs that
don't belong to the .NET version being analyzed:
- main/inflight/darc branches → allowed only for MainBranch=main
- netX.0 branches → allowed only when X matches MajorVersion
- release/X.* branches → allowed only when X matches MajorVersion

New -MainBranch parameter (default: 'main') tells the script which
branch owns the tags. For .NET 11, use -MainBranch net11.0.

Added 14 new Pester tests (72 total, all passing).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Single-PR mode no longer requires a tag to exist. Instead, it reads
MajorVersion and PatchVersion from eng/Versions.props at the PR's
merge commit SHA. This correctly handles:

- Tagged PRs: 10.0.50 at merge time → .NET 10 SR5
- Untagged PRs: 10.0.60 at merge time → .NET 10 SR6
- .NET 11 PRs: 11.0.0 at merge time → .NET 11.0 GA

Tag mode also auto-derives MajorVersion from the tag itself (e.g.,
-Tag 10.0.50 → MajorVersion=10), removing the need to pass it.

The -MajorVersion parameter default of 10 is kept as a fallback
for the tag search path only.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sub-patches are distinct milestones, not aliases for the parent SR.
10.0.41 maps to '.NET 10 SR4.1', not '.NET 10 SR4'. If that milestone
doesn't exist on GitHub, the script will fail explicitly rather than
silently milestoning to the wrong SR.

Removed Test-MilestoneMatch sub-patch folding (SR4.1 no longer matches SR4).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
PRs merged to inflight/current have merge commits that may not be
in the local clone's history. Now fetches the commit on demand
before reading Versions.props.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Uses pull_request_target (closed + merged) to trigger on every PR
merge to main, net*.0, inflight/*, and release/* branches. Reads
Versions.props at the merge commit to determine the correct
milestone, then applies it to the PR and its linked issues.

Uses -Apply (not dry-run) since this is the automated path.
No -CreateIssue since individual PR milestoning doesn't need reports.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@PureWeen PureWeen changed the title Add milestone drift detection and fix workflow for release tags Add automated milestone management on PR merge with tag-based reconciliation Apr 14, 2026
Merged milestone-on-merge.yml into fix-milestone-drift.yml as a single
'Milestone Management' workflow with two trigger modes:

- pull_request_target (closed+merged): auto-sets milestone on every
  PR merge using Versions.props at the merge commit
- workflow_dispatch: manual dry-run or tag reconciliation with inputs
  for pr_number, tag, apply, and create_issue

Also fixes shell injection from code review: all inputs now flow
through env vars instead of inline ${{ inputs.* }} interpolation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove duplicate Get-PrInfo call in Invoke-AnalyzeSinglePr (was
  fetching PR twice, wasting an API call and creating TOCTOU window)
- Add Write-Warning to Get-MainBranchForVersion when origin/main
  is unreachable (was silently falling back to net{Major}.0)
- Add Write-Warning to Get-VersionFromGitRef when merge commit
  Versions.props can't be read (was silently returning null)
- Handle GA tag in Invoke-AnalyzeRelease: use
  Get-PrNumbersReachableFromTag when no previous tag exists
  (was throwing 'Cannot determine previous tag')
- Guard PreviousTag access in Save-ReportJson with ContainsKey
  check (consistent with Write-Report and New-GitHubIssue)

73 Pester tests pass. E2E validated for both tagged and untagged PRs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@PureWeen PureWeen changed the title Add automated milestone management on PR merge with tag-based reconciliation Add automated milestone management with Versions.props detection Apr 14, 2026
github-actions Bot and others added 5 commits April 14, 2026 16:55
- Add contents: read to workflow permissions (required for checkout)
- Add Write-Warning for MajorVersion/PatchVersion parse failures in
  Get-VersionFromGitRef (was silently returning null)
- Initialize PrsSkippedWrongBranch in report hashtable, remove ?? 0
- Add test for 3-digit sub-patch: 10.0.101 → .NET 10 SR10.1

74 Pester tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove unreachable $alt search path in Find-MatchingMilestone
  (normalized loop already handles the .NET 10 SR5 ↔ .NET 10.0 SR5 case)
- Add prs_skipped_wrong_branch to Save-ReportJson summary block
  (was tracked and displayed in console but missing from JSON)
- Fix Get-AllMilestones pagination: break when data.Count < 100
  instead of looping when == 100 (avoids one extra API call on
  exact multiples of 100)

74 Pester tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Get-LinkedIssues: support bare 'close' and 'resolve' forms to match
  GitHub's auto-close spec (was only matching closes/closed/resolves/resolved)
- Get-MainBranchForVersion: distinguish version-mismatch (Write-Verbose)
  from read-failure (Write-Warning) instead of one misleading message
- Invoke-ApplyCorrections: track failure count and throw after all
  attempts so CI surfaces failures instead of exiting 0
- Rename Test-IsSrTag → Test-IsReleaseTag (also matches GA tags)

75 Pester tests pass (1 new test for close/resolve bare forms).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Single-PR mode: gracefully warn and skip when milestone doesn't exist
  yet (prevents red CI on every merge before milestone is pre-created)
- Tag mode: throw when PrsChecked=0 and Errors>0 (was misleadingly
  showing 'All milestones correct!' when nothing was checked)
- Extend milestone normalization to cover GA format ('.NET 10.0 GA'
  now matches '.NET 10 GA'), with 2 new tests
- Dedup AlreadyCorrect counter (issues linked from multiple PRs
  were double-counted)
- Apply corrections throw propagates failure count to CI

77 Pester tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
MajorVersion was always overwritten: tag mode derived it from the tag,
single-PR mode derived it from Versions.props at the merge commit. The
parameter default of 10 was a hardcoded value that would need updating.

Now: both analysis functions derive Major from the tag string. The
fallback path (Find-TagContainingPr) reads it from origin/main via
new Get-CurrentMajorVersion helper. Zero configuration needed.

77 Pester tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-project-automation github-project-automation Bot moved this from Todo to Approved in MAUI SDK Ongoing Apr 15, 2026
@PureWeen PureWeen merged commit 3c06583 into main Apr 16, 2026
4 of 5 checks passed
@PureWeen PureWeen deleted the feature/milestone-drift-fixer branch April 16, 2026 13:43
@github-project-automation github-project-automation Bot moved this from Approved to Done in MAUI SDK Ongoing Apr 16, 2026
PureWeen added a commit that referenced this pull request Apr 16, 2026
<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

## Summary

Follow-up to #34686. Adds preview/RC milestone support and release
branch detection to the milestone drift fixer.

## Problem

PRs merged to \`net11.0\` were not being milestoned because
\`Versions.props\` on that branch always has
\`PreReleaseVersionIteration=1\` regardless of which preview the PR
actually ships in. The iteration is only bumped on release branches.

## Solution

### Release Branch Detection (Primary)

New detection step checks release branches first using \`merge-base
--is-ancestor\`. For each PR, it finds the **earliest** release branch
containing the merge commit:

| Release Branch | Milestone |
|---|---|
| \`release/10.0.1xx\` | \`.NET 10.0 GA\` |
| \`release/10.0.1xx-sr5\` | \`.NET 10 SR5\` |
| \`release/11.0.1xx-preview1\` | \`.NET 11.0-preview1\` |
| \`release/11.0.1xx-preview3\` | \`.NET 11.0-preview3\` |
| \`release/12.0.1xx-rc1\` | \`.NET 12.0-rc1\` |

### Detection Order

1. **Explicit \`-Tag\`** — if provided
2. **Release branches** — \`merge-base --is-ancestor\` against
\`release/{Major}.0.1xx-*\` branches, earliest match wins
3. **Versions.props** at merge commit — fallback for PRs not yet on any
release branch
4. **Tag range search** — last resort

### Preview/RC Milestone Mapping

\`ConvertTo-Milestone\` now accepts optional pre-release label and
iteration:

| Input | Milestone |
|---|---|
| \`11.0.0 + preview + 3\` | \`.NET 11.0-preview3\` |
| \`12.0.0 + rc + 1\` | \`.NET 12.0-rc1\` |
| \`10.0.60\` (stable) | \`.NET 10 SR6\` (unchanged) |

## Validated Results

| PR | Base | Current Milestone | Script Result | Method |
|---|---|---|---|---|
| #33524 | net11.0 | .NET 11.0-preview1 | .NET 11.0-preview1 ✅ | Release
branch |
| #33233 | net11.0 | .NET 11.0-preview1 | .NET 11.0-preview1 ✅ | Release
branch |
| #30132 | net11.0 | .NET 11.0-preview3 | .NET 11.0-preview3 ✅ | Release
branch |
| #33834 | net11.0 | .NET 11.0-preview3 | .NET 11.0-preview3 ✅ | Release
branch |
| #34214 | net11.0 | .NET 11.0-preview2 | .NET 11.0-preview3 ✅ | Release
branch (drift caught!) |
| #34945 | net11.0 | .NET 11.0-preview4 | preview1 (fallback) |
Versions.props (no p4 branch yet) |
| #34620 | main | .NET 10 SR6 | .NET 10 SR6 ✅ | Release branch |
| #34047 | main | .NET 10 SR4.1 | .NET 10 SR5 ✅ | Release branch (drift
caught!) |

PR #34214 is a real drift example: milestoned preview2 by a human, but
actually on the preview3 release branch.

## Test Suite

88 Pester tests (11 new):
- 6 for \`ConvertTo-Milestone\` preview/RC mapping
- 5 for \`ConvertBranchToMilestone\` (GA, SR, preview, RC, non-release)

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions github-actions Bot locked and limited conversation to collaborators May 17, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants