Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions .github/agents/release-manager.agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: >
prepare-release (monthly release prep: stage internal branch + dependency updates; servicing prep:
backport selected main commits onto release/* and bump patch version), publish-release (monthly release:
land to internal/release + publish/promote; servicing: run official build from release/* then publish),
validate-release (verify Source Link/symbols on msdl, reconcile branches when applicable), and
validate-release (verify package dependency resolution and Source Link/symbols on msdl, reconcile branches when applicable), and
write-release-notes (draft GitHub release notes for a tag).
USE FOR: "prepare for a release", "prepare internal release branch", "stage the release",
"prepare a servicing release", "choose servicing backports", "update release dependencies",
Expand Down Expand Up @@ -111,6 +111,8 @@ verification script lives at `release-manager/validate-release/scripts/Test-Sour
branches. Resolve each by its **URL**, not by remote name -- names vary by machine. Do not rely on
absolute on-disk clone paths.
- **Release notes** are never published to a GitHub release without explicit user confirmation.
- **Package scope and dependency integrity.** Whenever package scope is determined, follow
[release-manager/references/package-scope-and-dependency-validation.md](release-manager/references/package-scope-and-dependency-validation.md).
- **Release wrap-up.** When the full release process is complete (GitHub release published, any
required branch reconciliation done), present a short celebratory closing message that:
- Confirms the release version and packages shipped.
Expand All @@ -126,11 +128,11 @@ There are two supported release tracks:
1. **Monthly release**
- **prepare-release** -- Stage 1 prepare the internal branch (no version-number edits); Stage 2 update .NET 9, then .NET 8, then .NET 10 dependencies (three sub-stages).
- **publish-release** -- Stage 3 build from `internal/release/<major>.<minor>` (gated on a green official build); Stage 4 publish to nuget.org and **promote the official release build to the public `.NET <major>` channel**.
- **validate-release** -- Stage 5 verify Source Link/symbols on msdl; Stage 6 reconcile internal -> public `release/<major>.<minor>` -> `main`; Stage 7 confirm the support-page update.
- **validate-release** -- Stage 5 verify exact-version dependency resolution and Source Link/symbols on msdl; Stage 6 reconcile internal -> public `release/<major>.<minor>` -> `main`; Stage 7 confirm the support-page update.

2. **Servicing release**
- **prepare-release** -- prepare directly on `release/<major>.<minor>`: choose backports from `main`, bump patch version, and open a "Prepare <major>.<minor>.<patch> Servicing Release" PR.
- **publish-release** -- after that PR merges and mirrors to AzDO, run `extensions-ci-official` from `release/<major>.<minor>` and publish the selected package scope.
- **validate-release** -- run Source Link verification and post-release checks with the servicing package scope; run reconciliation only when explicitly needed.
- **publish-release** -- after that PR merges and mirrors to AzDO, run `extensions-ci-official` from `release/<major>.<minor>` and publish the selected packages plus their full `dotnet/extensions` dependency closure.
- **validate-release** -- verify exact-version dependency resolution and Source Link with the final published manifest; run reconciliation only when explicitly needed.

Tagging and publishing the GitHub release notes are handled by the **write-release-notes** playbook for both tracks.
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,11 @@ Prompt the user to select rows from the **selectable candidate table only** (for

Do not cherry-pick until selection is explicit.

## Step 5: Confirm package scope and template inclusion
## Step 5: Confirm selected roots and provisional dependency closure

Before committing:

1. Propose the package scope derived from selected items (default to coherent related package sets). For example, when any of Microsoft.Extensions.AI, Microsoft.Extensions.AI.Abstractions, and Microsoft.Extensions.AI.OpenAI are updated, all three are released, but the Microsoft.Extensions.AI.Evaluation packages are not released unless they are also updated.
2. Ask the user to confirm or adjust that package scope.
3. If selected changes affect packages used by project templates, ask whether template packages should also be included in the servicing release.

Record this confirmed scope; it is the source of truth for publish/validate/release-notes stages.
Derive the selected roots from the chosen commits and explicit human additions, then follow
[package scope and dependency validation](../../references/package-scope-and-dependency-validation.md)
to approve and record the provisional manifest in the servicing-prep PR.

## Step 6: Apply commits in servicing order

Expand Down Expand Up @@ -168,8 +164,19 @@ PR title format:
PR body format:

```md
Prepares the <major>.<minor>.<patch> servicing release for the following packages:
- <package-name> (<version-if-different-or-prerelease>)
Prepares the <major>.<minor>.<patch> servicing release.

## Selected packages
- <package-name> (<version>) — <independent change/selection reason>
- <package-name> (<version>) — <independent change/selection reason>

## Dependency-closure packages
- <package-name> (<version>) — required by <parent-package> (<exact dependency requirement>)
- None

The dependency closure is provisional until recomputed from the official build's PackageArtifacts.

## Packages in the complete provisional release scope
- <package-name> (<version-if-different-or-prerelease>)
- <package-name> (<version-if-different-or-prerelease>)

Expand All @@ -192,19 +199,14 @@ Notes:

## Step 8: Preserve scope for downstream stages

After PR creation, treat the merged servicing-prep PR description as authoritative for:

- package publish scope (publish-release),
- package validation scope (validate-release),
- package scope in release notes (write-release-notes).

If scope changes later, update the PR description and confirm with the user before publishing.
Keep the PR description current if selected roots change: recompute the provisional closure and
obtain approval again. Publish-release replaces it with the approved artifact-derived final scope.

## After this preparation

After the servicing-prep PR merges into `release/<major>.<minor>`, continue with **publish-release** servicing flow:

1. wait for mirror into AzDO,
2. run `extensions-ci-official` from `release/<major>.<minor>`,
3. publish selected packages,
3. recompute closure from official artifacts and publish selected plus dependency-closure packages,
4. continue post-release checks and notes.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Unlike the monthly release flow, there is no `stage-release-*` -> `internal/rele
## Prerequisites

- The servicing-prep PR into `release/<major>.<minor>` is merged.
- You know the package scope from that PR description.
- You know the selected package roots and provisional closure from that PR description.
- You have access to Azure DevOps and the `extensions-ci-official` pipeline.

## Steps
Expand All @@ -20,6 +20,9 @@ Unlike the monthly release flow, there is no `stage-release-*` -> `internal/rele
- AzDO build run URL
- AzDO build ID / build number
- BAR build ID for the official release build
6. Derive the authoritative artifact manifest from the official `PackageArtifacts` `.nuspec` files
by following [package scope and dependency validation](../../references/package-scope-and-dependency-validation.md).
7. Reconcile it with the PR's provisional manifest and obtain explicit approval before Stage 4.

## Notes

Expand All @@ -32,4 +35,5 @@ Unlike the monthly release flow, there is no `stage-release-*` -> `internal/rele
Proceed to **Stage 4 - Publish and Promote** using:

- the official release build from this stage, and
- the servicing package scope captured in the merged servicing-prep PR description.
- the selected roots captured in the merged servicing-prep PR description, and
- the approved artifact-derived dependency closure from this stage.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ This stage is operational and produces no commit. Both actions are **irreversibl
- Stage 3 is complete: the official release build succeeded and produced the `PackageArtifacts`.
- For the channel promotion: the `darc` CLI, authenticated to the Build Asset Registry (BAR).

For servicing releases, also require the merged servicing-prep PR description; it is the source of truth for package scope.
For servicing releases, also require the merged servicing-prep PR description for selected roots and
the approved artifact-derived closure from Stage 3.

## Execution context check

Expand All @@ -29,15 +30,15 @@ Publishing is irreversible (a published version cannot be overwritten or truly d
1. Download and extract the `PackageArtifacts` from the official build.
- If in-session artifact download/auth fails, hand off this step to the user's terminal and ask
them to return the local extracted package folder path.
2. Stage the packages to publish into a clean folder:
- Always exclude `Microsoft.Internal.*`.
- For **servicing releases**, start from the package list in the merged servicing-prep PR description; treat that list as canonical unless the user explicitly changes it.
- For **monthly releases**, include all release packages except those the user explicitly holds back.
- In both tracks, flag template/tooling packages (for example `*.ProjectTemplates`) for an explicit include/exclude decision.
3. Present the excluded and to-publish lists for the user to review.
2. Build and obtain approval for the artifact-derived manifest by following
[package scope and dependency validation](../../references/package-scope-and-dependency-validation.md).
Treat any required `Microsoft.Internal.*` package as a blocking packaging error.
3. Validate the approved manifest's dependencies as required by that shared invariant before any push.
4. Two nuget.org accounts are involved: almost all packages publish from the **dotnetframework** account; **`Microsoft.Agents.AI.ProjectTemplates`** publishes from the **MicrosoftAgentFramework** account, so it must be pushed separately with that account's key.
5. The **user** runs `dotnet nuget push` with the appropriate API key(s) in their terminal (outside
5. Order the staged package paths dependency-first where possible. The **user** runs `dotnet nuget push` with the appropriate API key(s) in their terminal (outside
the agent session). Never run the push, and never handle the API keys.
6. After propagation, repeat the shared invariant's dependency validation and record the approved
**final published manifest** for validate-release and write-release-notes.

### Secure API key entry (user-run helper)

Expand Down Expand Up @@ -118,6 +119,7 @@ run it in terminal, then report:

- staged package path(s),
- push output summary,
- post-publish exact-version dependency-resolution results for every published package,
- confirmation that the nuget.org API key was deleted/regenerated.

## Sub-stage 2 - Ensure the official release build is on the public channel
Expand All @@ -136,4 +138,6 @@ Determine whether manual promotion is required:

## After the stage

This stage produces no repository commit. Next, run the **validate-release** playbook: verify Source Link and symbols on msdl (Stage 5), reconcile the branches (Stage 6), and confirm the support-page listing (Stage 7).
This stage produces no repository commit. Next, run the **validate-release** playbook: independently
verify exact-version dependency resolution plus Source Link and symbols on msdl (Stage 5), reconcile
the branches (Stage 6), and confirm the support-page listing (Stage 7).
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Package Scope and Dependency Validation

Whenever package scope is determined:

1. Separate independently changed or human-selected packages (**Selected**) from packages included
only because an in-scope package depends on them (**Dependency closure**).
2. Recursively include every direct/transitive dependency produced by `dotnet/extensions` that is
required at the release version. Record the requiring parent and exact dependency requirement.
3. Present both groups separately and obtain explicit human approval. Recompute after every scope
adjustment; a dependency-required package cannot be held back.

Monthly releases start with all releasable packages. Servicing releases start with selected roots.
Preparation may use project metadata provisionally, but the official `PackageArtifacts` `.nuspec`
files determine the final closure and published manifest.

Before publishing, verify every in-scope exact-version dependency resolves from staged artifacts or
approved sources. After propagation, repeat the check for every published package from clean,
consumer-visible sources, including packages without `lib` DLLs. Record the source and result.
Unresolved dependencies block publishing, validation, and release-note finalization.
15 changes: 11 additions & 4 deletions .github/agents/release-manager/validate-release/README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
# Validate Release

Confirms a published `dotnet/extensions` release is correct and finalizes it: verify that the published symbols are on the Microsoft symbol server (msdl) with working Source Link, then reconcile the internal, public, and `main` branches.
Confirms a published `dotnet/extensions` release is correct and finalizes it: verify every published
package's exact-version dependencies resolve, verify that published symbols are on the Microsoft
symbol server (msdl) with working Source Link, then reconcile the internal, public, and `main`
branches.

Run this playbook after **publish-release**.

- Stage 5 is automated symbol verification.
- Stage 5 verifies package dependency resolution and symbols.
- Stage 6 stages reconciliation merges when needed (pushing and PR completion are left to the user).
- Stage 7 handles support-page follow-up based on release type and package novelty.

For servicing releases prepared directly on public `release/<major>.<minor>`, Stage 6 is often unnecessary because commits were backported from `main` into the release branch up front. In that case, run Stage 5, follow the Stage 7 decision gate (skip if applicable), and run Stage 6 only if the user explicitly asks for additional branch-flow follow-up.

## Stage 5 - Verify Source Link and Symbols
## Stage 5 - Verify Package Dependencies, Source Link, and Symbols

Run the Source Link sweep against the published packages until every library package reports `valid` on msdl. This is the **release sign-off gate** -- a persistent `symbols-not-indexed` result means the official release build never reached the public `.NET <major>` channel (see publish-release, Stage 4).
First verify every published package's exact-version dependencies resolve from clean,
consumer-visible sources. Then run the Source Link sweep until every library package reports `valid`
on msdl. Both checks are **release sign-off gates**: unresolved dependencies block completion, and a
persistent `symbols-not-indexed` result means the official release build never reached the public
`.NET <major>` channel (see publish-release, Stage 4).

Read and follow [references/stage-5-verify-source-link.md](references/stage-5-verify-source-link.md).

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
# Stage 5 - Verify Source Link and Symbols
# Stage 5 - Verify Package Dependencies, Source Link, and Symbols

The publish-release playbook published the packages to nuget.org and promoted/assigned the official release build to the public `.NET <major>` channel. Only after that assignment do symbols publish to the Microsoft symbol server (msdl). Verify Source Link and symbol-server availability -- this is the **release sign-off gate**.
The publish-release playbook published the packages to nuget.org and promoted/assigned the official
release build to the public `.NET <major>` channel. Verify exact-version dependency resolution first.
Only after channel assignment do symbols publish to the Microsoft symbol server (msdl), so then verify
Source Link and symbol-server availability. Both checks are **release sign-off gates**.
Comment thread
jeffhandley marked this conversation as resolved.

## Prerequisites

- publish-release is complete: packages published to nuget.org and the official release build assigned/promoted to the public `.NET <major>` channel.
- The `sourcelink` and `dotnet-symbol` global tools (`dotnet tool install -g sourcelink`; `dotnet tool install -g dotnet-symbol`).
- The package scope for this release is known:
- Monthly release: the full release package set.
- Servicing release: the package list from the merged servicing-prep PR description (unless the user explicitly changed scope at publish time).
- The final published manifest from publish-release is known. It is authoritative for both tracks and
identifies selected packages separately from dependency-closure packages. For servicing releases,
do not fall back to the provisional package list in the servicing-prep PR.

## Verify
## Sub-stage 1 - Verify exact-version dependency resolution

Follow [package scope and dependency validation](../../references/package-scope-and-dependency-validation.md).

Apply the shared invariant to every package in the final published manifest, record its required
resolution report, and obtain explicit approval before Source Link verification. Allow bounded
retries for expected propagation delay, but do not proceed with unresolved dependencies.

## Sub-stage 2 - Verify Source Link and symbols

Run the Source Link sweep against the folder containing the published packages for this release scope:

Expand All @@ -27,8 +38,14 @@ For each `.nupkg` the script extracts a lib DLL, pulls the matching PDB from the

Indexing on msdl lags the promotion/channel assignment, so `symbols-not-indexed` immediately afterward is expected -- **re-run until every published library package in scope is `valid`**. If packages stay `symbols-not-indexed` well after publish, re-confirm the official release build is actually on the public `.NET <major>` channel (`darc get-build --id <bar-id>` should list `.NET <major>`). Investigate any `sourcelink-FAILED`.

**Do not sign off the release until every published library package in scope reports `valid`.**
**Do not sign off the release until every published package's exact-version dependencies resolve and
every published library package in scope reports `valid`.**

## After the stage

Once every library package is `valid`, the release symbols are public. Continue with **Stage 6 - Reconcile Branches**.
Once dependency resolution passes and every library package is `valid`, the package graph and symbols
are public:

- **Monthly release:** continue with **Stage 6 - Reconcile Branches**.
- **Servicing release:** continue with **Stage 7 - Support-Page Follow-up** unless the user explicitly
requested Stage 6 reconciliation.
Loading