documentation/release-checklist.md
Fill in these values before starting. Version increments are irregular — they must be specified explicitly.
| Placeholder | Description | Value |
|---|---|---|
{{PREVIOUS_RELEASE_VERSION}} | Version being replaced as latest (e.g. 18.5) | |
{{THIS_RELEASE_VERSION}} | Version being released now (e.g. 18.6) | |
{{THIS_RELEASE_EXACT_VERSION}} | Full VersionPrefix from eng/Versions.props on the release branch after final branding (e.g. 18.6.0). For non-patch releases this is always {{THIS_RELEASE_VERSION}}.0. | |
{{NEXT_VERSION}} | Version that main will be bumped to (e.g. 18.7) | |
{{BRANCH_SNAP_DATE}} | Date MSBuild branches vs* from main. Insertion targets VS main. From VS-Dates wiki | |
{{INSIDERS_SNAP_DATE}} | Date VS snaps main → rel/insiders. Final-branded MSBuild must be in VS main before this date. From VS-Dates wiki | |
{{STABLE_SNAP_DATE}} | Date VS snaps rel/insiders → rel/stable. From VS-Dates wiki | |
{{VS_SHIP_DATE}} | Date VS ships publicly (GA). Post-GA tasks (nuget.org, docs) happen after this. |
Derived values (do not edit — computed from inputs):
vs{{THIS_RELEASE_VERSION}}VS {{THIS_RELEASE_VERSION}}VS {{NEXT_VERSION}}main (VS snaps main → insiders → stable on its own schedule)Trigger: User decides to start a release. Do this first.
eng/Versions.props on main has VersionPrefix = {{THIS_RELEASE_VERSION}}.0 — if not, the inputs are wrongvs{{THIS_RELEASE_VERSION}} does not already exist — if it does, this release was already startedVS {{THIS_RELEASE_VERSION}} exists: darc get-channel --name "VS {{THIS_RELEASE_VERSION}}" darc add-channel --name "VS {{THIS_RELEASE_VERSION}}"{{PLACEHOLDERS}} replaced| Artifact | URL |
|---|---|
| Next-version branding PR | {{URL_OF_NEXT_VERSION_BRANDING_PR}} |
| VisualStudio.ChannelName PR | {{URL_OF_CHANNEL_NAME_PR}} |
| Phase 1 DARC config PR | {{URL_OF_PHASE1_DARC_PR}} |
| Phase 3 DARC config PR | {{URL_OF_PHASE3_DARC_PR}} |
| Final branding PR | {{URL_OF_FINAL_BRANDING_PR}} |
| VS insertion PR | {{URL_OF_VS_INSERTION}} |
| Channel promotion PR | {{URL_OF_CHANNEL_PROMOTION_PR}} |
Trigger:
{{BRANCH_SNAP_DATE}}reached.
Steps are sequential — complete in order.
vs{{THIS_RELEASE_VERSION}} from HEAD of main: git push upstream HEAD:refs/heads/vs{{THIS_RELEASE_VERSION}}
git push upstream <correct_sha>:refs/heads/vs{{THIS_RELEASE_VERSION}}--configuration-branch release/msbuild-{{THIS_RELEASE_VERSION}} on every command and --no-pr on all but the last:
darc get-default-channels --channel "VS {{THIS_RELEASE_VERSION}}" --branch vs{{THIS_RELEASE_VERSION}} --source-repo https://github.com/dotnet/msbuild No matching channels were found.: darc add-default-channel --channel "VS {{THIS_RELEASE_VERSION}}" --branch vs{{THIS_RELEASE_VERSION}} --repo https://github.com/dotnet/msbuild --configuration-branch release/msbuild-{{THIS_RELEASE_VERSION}} --no-prdarc add-channel --name "VS {{NEXT_VERSION}}" --configuration-branch release/msbuild-{{THIS_RELEASE_VERSION}} --no-pr --no-pr to create the PR): darc add-default-channel --channel "VS {{NEXT_VERSION}}" --branch vs{{NEXT_VERSION}} --repo https://github.com/dotnet/msbuild --configuration-branch release/msbuild-{{THIS_RELEASE_VERSION}}VS {{NEXT_VERSION}} channel available as a promotion target: {{URL_OF_CHANNEL_PROMOTION_PR}}.config/git-merge-flow-config.jsonc: vs{{THIS_RELEASE_VERSION}} as the last entry before main in the merge chain. Add a comment noting the VS/SDK version context.Trigger:
vs{{THIS_RELEASE_VERSION}}branch exists (Phase 1.1 done). Previous release is in insiders stage.
Create one PR in main containing all of the following changes:
eng/Versions.props: Update VersionPrefix to {{NEXT_VERSION}}.0eng/Versions.props: Update PackageValidationBaselineVersion to the last released version (the {{PREVIOUS_RELEASE_VERSION}} GA version published to nuget.org).CompatibilitySuppressions.xml files. Run: dotnet pack MSBuild.Dev.slnf /p:ApiCompatGenerateSuppressionFile=true azure-pipelines/vs-insertion.yml: set AutoInsertTargetBranch for vs{{THIS_RELEASE_VERSION}} → VS main.azure-pipelines/vs-insertion-experimental.yml: rel/insiders and/or rel/stable to TargetBranch parameter values if not already present.Trigger: Phase 2 branding PR merged (main now has
{{NEXT_VERSION}}version).
First, gather information (read-only queries — no PR needed):
darc get-subscriptions --exact --source-repo https://github.com/dotnet/msbuild --channel "VS {{THIS_RELEASE_VERSION}}" main branch entry.darc get-default-channels --source-repo https://github.com/dotnet/msbuild --branch vs{{THIS_RELEASE_VERSION}} Then, batch all write operations into one PR on the maestro-configuration repo.
Use --configuration-branch release/msbuild-{{THIS_RELEASE_VERSION}}-main-bump and --no-pr on all but the last command:
darc delete-default-channel --repo https://github.com/dotnet/msbuild --branch main --channel "VS {{THIS_RELEASE_VERSION}}" --configuration-branch release/msbuild-{{THIS_RELEASE_VERSION}}-main-bump --no-prdarc add-default-channel --channel "VS {{NEXT_VERSION}}" --branch main --repo https://github.com/dotnet/msbuild --configuration-branch release/msbuild-{{THIS_RELEASE_VERSION}}-main-bump --no-prdarc update-subscription --id <subscription_id_from_3.1> --channel "VS {{NEXT_VERSION}}" --configuration-branch release/msbuild-{{THIS_RELEASE_VERSION}}-main-bump --no-prdarc add-default-channel --channel "VS {{THIS_RELEASE_VERSION}}" --branch vs{{THIS_RELEASE_VERSION}} --repo https://github.com/dotnet/msbuild --configuration-branch release/msbuild-{{THIS_RELEASE_VERSION}}-main-bump --no-pr--no-pr.--no-pr to open the PR on the configuration branch.Verifications (parallel — read-only, no ordering dependency):
darc get-subscriptions --exact --target-repo https://github.com/dotnet/msbuild --source-repo https://github.com/dotnet/arcadedarc get-subscriptions --exact --target-repo https://github.com/dotnet/msbuild --source-repo https://github.com/nuget/nuget.clientdarc get-subscriptions --exact --target-repo https://github.com/dotnet/msbuild --source-repo https://github.com/dotnet/roslynEnabled: False in output). We do not want to automatically bump them — version updates are driven by SDK or VS.darc add-subscription / darc update-subscription (run with --help for params)Trigger: 7 calendar days before
{{INSIDERS_SNAP_DATE}}.
Precondition: Phases 1–3 complete. Preview builds fromvs{{THIS_RELEASE_VERSION}}have been inserting into VSmainsince Phase 2.
Goal: Final-brand the release branch and get the final-branded bits inserted into VSmainbefore VS snaps torel/insiders.
Steps are sequential.
vs{{THIS_RELEASE_VERSION}} branch: PublicAPI.Unshipped.txt → PublicAPI.Shipped.txt for all projects with API changes. See release.md for details.scripts/Stabilize-Release.ps1 on vs{{THIS_RELEASE_VERSION}} branch: -DryRun first to preview. The script adds <DotNetFinalVersionKind>release</DotNetFinalVersionKind> on the same line as VersionPrefix (creates merge conflict for forward-flow) and changes PreReleaseVersionLabel from preview to servicing. vs{{THIS_RELEASE_VERSION}}: {{URL_OF_FINAL_BRANDING_PR}}vs{{THIS_RELEASE_VERSION}}:
vs{{THIS_RELEASE_VERSION}} with Optional OptProfDrop Override set to main's latest OptProf drop path. (Find the path in main CI logs: Windows_NT → Build → search for OptimizationData.) Alternatively, set SkipApplyOptimizationData to true in Advanced options.vs{{THIS_RELEASE_VERSION}}. If not triggered, run manually ('Run pipeline' in upper right).vs{{THIS_RELEASE_VERSION}} with no overrides — OptProf should succeed now.vs{{THIS_RELEASE_VERSION}} into VS main (auto-generated at https://devdiv.visualstudio.com/DevDiv/_git/VS/pullrequests). The final-branded bits must be in VS main before {{INSIDERS_SNAP_DATE}} so they are included when VS snaps to rel/insiders: {{URL_OF_VS_INSERTION}} After insiders snap (only if a backport to insiders is needed):
azure-pipelines/vs-insertion.yml: retarget AutoInsertTargetBranch for vs{{THIS_RELEASE_VERSION}} from VS main → rel/insiders. This enables direct insertion of hotfix commits into the insiders branch.After stable snap (only if a backport to stable is needed):
azure-pipelines/vs-insertion.yml: retarget AutoInsertTargetBranch for vs{{THIS_RELEASE_VERSION}} → rel/stable. This enables direct insertion of hotfix commits into the stable branch.Trigger:
{{VS_SHIP_DATE}}has passed and VS release has shipped.
Steps are mostly parallel unless noted.
5.1 Push packages to nuget.org. Contact dnceng — search "Publish MSBuild {{THIS_RELEASE_VERSION}} to NuGet.org" email subject for template.
THIS_RELEASE_EXACT_VERSION = VersionPrefix from eng/Versions.props on the release branch (also visible in the VS insertion PR). Packages to publish taken from the official build https://devdiv.visualstudio.com/DevDiv/_build?definitionId=9434 for the {{THIS_RELEASE_VERSION}} branch; search in artifacts under the Shipping folder for:
5.2 Publish docs: submit reference request at https://aka.ms/publishondocs
Click Request – Reference Publishing. Use existing ticket as a reference.
5.3 Create GitHub release:
git checkout <final-branding commit on vs{{THIS_RELEASE_VERSION}}>
git tag v{{THIS_RELEASE_EXACT_VERSION}}
git push upstream v{{THIS_RELEASE_EXACT_VERSION}}
Create release at https://github.com/dotnet/msbuild/releases/new — use Generate Release Notes to prepopulate.
5.4 Update BootstrapSdkVersion in eng/Versions.props if a fresh SDK was released. Check https://dotnet.microsoft.com/download/visual-studio-sdks — always verify the details for the targeted .NET version.
5.5 Extend OptProf data expiration for vs{{THIS_RELEASE_VERSION}} branch if the release is LTSC:
OptimizationData/DotNet-msbuild-Trusted/vs{{THIS_RELEASE_VERSION}}/... (in MSBuild CI logs: Build task, or OptProf pipeline: "Publish OptimizationInputs drop" task) 5.6 Verify main subscriptions point to VS {{NEXT_VERSION}} channel (should have been done in Phase 3; confirm):
darc get-subscriptions --exact --target-repo https://github.com/dotnet/msbuild --target-branch main
5.7 Review this tracking issue for any process deviations. If the process changed, create a PR to update documentation/release-checklist.md with the improvements.