diff --git a/.github/agents/release-manager.agent.md b/.github/agents/release-manager.agent.md index 723f18b0c3e..fca7f588a2d 100644 --- a/.github/agents/release-manager.agent.md +++ b/.github/agents/release-manager.agent.md @@ -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", @@ -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. @@ -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/.` (gated on a green official build); Stage 4 publish to nuget.org and **promote the official release build to the public `.NET ` channel**. - - **validate-release** -- Stage 5 verify Source Link/symbols on msdl; Stage 6 reconcile internal -> public `release/.` -> `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/.` -> `main`; Stage 7 confirm the support-page update. 2. **Servicing release** - **prepare-release** -- prepare directly on `release/.`: choose backports from `main`, bump patch version, and open a "Prepare .. Servicing Release" PR. - - **publish-release** -- after that PR merges and mirrors to AzDO, run `extensions-ci-official` from `release/.` 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/.` 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. diff --git a/.github/agents/release-manager/prepare-release/references/stages-1-2-servicing-branch.md b/.github/agents/release-manager/prepare-release/references/stages-1-2-servicing-branch.md index 94777a8233d..7c114e81424 100644 --- a/.github/agents/release-manager/prepare-release/references/stages-1-2-servicing-branch.md +++ b/.github/agents/release-manager/prepare-release/references/stages-1-2-servicing-branch.md @@ -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 @@ -168,8 +164,19 @@ PR title format: PR body format: ```md -Prepares the .. servicing release for the following packages: -- () +Prepares the .. servicing release. + +## Selected packages +- () — +- () — + +## Dependency-closure packages +- () — required by () +- None + +The dependency closure is provisional until recomputed from the official build's PackageArtifacts. + +## Packages in the complete provisional release scope - () - () @@ -192,13 +199,8 @@ 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 @@ -206,5 +208,5 @@ After the servicing-prep PR merges into `release/.`, continue with 1. wait for mirror into AzDO, 2. run `extensions-ci-official` from `release/.`, -3. publish selected packages, +3. recompute closure from official artifacts and publish selected plus dependency-closure packages, 4. continue post-release checks and notes. diff --git a/.github/agents/release-manager/publish-release/references/stage-3-build-servicing.md b/.github/agents/release-manager/publish-release/references/stage-3-build-servicing.md index d1d2f75b8ac..e8b01a7d242 100644 --- a/.github/agents/release-manager/publish-release/references/stage-3-build-servicing.md +++ b/.github/agents/release-manager/publish-release/references/stage-3-build-servicing.md @@ -7,7 +7,7 @@ Unlike the monthly release flow, there is no `stage-release-*` -> `internal/rele ## Prerequisites - The servicing-prep PR into `release/.` 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 @@ -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 @@ -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. diff --git a/.github/agents/release-manager/publish-release/references/stage-4-publish-and-promote.md b/.github/agents/release-manager/publish-release/references/stage-4-publish-and-promote.md index 626c3e3d8e8..e8ffe75d5d4 100644 --- a/.github/agents/release-manager/publish-release/references/stage-4-publish-and-promote.md +++ b/.github/agents/release-manager/publish-release/references/stage-4-publish-and-promote.md @@ -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 @@ -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) @@ -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 @@ -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). diff --git a/.github/agents/release-manager/references/package-scope-and-dependency-validation.md b/.github/agents/release-manager/references/package-scope-and-dependency-validation.md new file mode 100644 index 00000000000..66c3031bbfb --- /dev/null +++ b/.github/agents/release-manager/references/package-scope-and-dependency-validation.md @@ -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. diff --git a/.github/agents/release-manager/validate-release/README.md b/.github/agents/release-manager/validate-release/README.md index b762aa009ca..85c9de02dd1 100644 --- a/.github/agents/release-manager/validate-release/README.md +++ b/.github/agents/release-manager/validate-release/README.md @@ -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/.`, 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 ` 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 ` channel (see publish-release, Stage 4). Read and follow [references/stage-5-verify-source-link.md](references/stage-5-verify-source-link.md). diff --git a/.github/agents/release-manager/validate-release/references/stage-5-verify-source-link.md b/.github/agents/release-manager/validate-release/references/stage-5-verify-source-link.md index a779e77a1e4..4362124e7ea 100644 --- a/.github/agents/release-manager/validate-release/references/stage-5-verify-source-link.md +++ b/.github/agents/release-manager/validate-release/references/stage-5-verify-source-link.md @@ -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 ` 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 ` 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**. ## Prerequisites - publish-release is complete: packages published to nuget.org and the official release build assigned/promoted to the public `.NET ` 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: @@ -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 ` channel (`darc get-build --id ` should list `.NET `). 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. diff --git a/.github/agents/release-manager/write-release-notes/references/format-template.md b/.github/agents/release-manager/write-release-notes/references/format-template.md index 3a50562ba4c..9ee3c2c8162 100644 --- a/.github/agents/release-manager/write-release-notes/references/format-template.md +++ b/.github/agents/release-manager/write-release-notes/references/format-template.md @@ -69,19 +69,20 @@ Use this template when all packages ship together (e.g. v10.3.0 → v10.4.0). ## Targeted patch release -Use this template when only a subset of packages ships (e.g. v10.3.1). +Use this template when only a subset of packages ships (e.g. v10.3.1). Use the final published +manifest produced under [package scope and dependency validation](../../references/package-scope-and-dependency-validation.md). ```markdown -[Optional preamble — state which packages are patched and why. Example: "This patch release addresses issues in the AI and HTTP Resilience packages." May be omitted.] +[Optional preamble — 2–3 sentences summarizing the release theme. May be omitted.] ## Packages in this release -[Only the patched packages] +[The complete final published manifest] | Package | Version | |---------|---------| -| Microsoft.Extensions.AI | 10.3.1 | -| Microsoft.Extensions.AI.Abstractions | 10.3.1 | +| Package.A | `` | +| Package.B | `` | ## What's Changed @@ -99,8 +100,11 @@ Use this template when only a subset of packages ships (e.g. v10.3.1). ## Section rules -1. **Preamble** — optional. If included, summarize the release theme. For patch releases, if included, name the affected packages. Suggest a couple of options to the user and always offer the option of omitting it. -2. **Packages in this release** — for patch releases only. Table of affected packages and versions. Omit for full releases (all packages ship at the same version). +1. **Preamble** — optional. If included, summarize the release theme. Suggest a couple of options to + the user and always offer the option of omitting it. +2. **Packages in this release** — for patch releases only. Table of the complete final published + manifest with package ID and version only. Omit for full releases when all packages ship at the + same version with no scope exceptions. 3. **Breaking Changes** — only for stable API breaks (very rare). Omit if none. 4. **Experimental API Changes** — omit if no experimental changes. Omit empty subsections within. 5. **What's Changed** — grouped by area. Order areas by activity (most entries first). Omit areas with no entries.