-
Notifications
You must be signed in to change notification settings - Fork 863
Add a Release-Notes skill #7390
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
jeffhandley
merged 4 commits into
dotnet:main
from
jeffhandley:jeffhandley/release-notes
Mar 18, 2026
Merged
Changes from 2 commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
aa71677
Add release-notes skill initial implementation
jeffhandley 621b263
Revise release-notes skill based on v10.4.0 experience
jeffhandley 6dd6725
Apply suggestions from Copilot review
jeffhandley 507444d
Add pr_coauthors table and use it for acknowledgements
jeffhandley File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,132 @@ | ||
| --- | ||
| name: release-notes | ||
| description: 'Draft release notes for a dotnet/extensions release. Gathers merged PRs, assigns them to packages by file path, categorizes by area and impact, tracks experimental API changes, and produces formatted markdown suitable for a GitHub release. Handles both monthly full releases and targeted intra-month patch releases.' | ||
| agent: 'agent' | ||
| tools: ['github/*'] | ||
| --- | ||
|
|
||
| # Release Notes | ||
|
|
||
| Draft release notes for a `dotnet/extensions` release. This skill gathers merged PRs between two tags, maps them to affected packages by examining changed file paths, categorizes entries by area and impact, audits experimental API changes, and produces concise markdown suitable for a GitHub release. | ||
|
|
||
| > **User confirmation required: This skill NEVER publishes a GitHub release without explicit user confirmation.** The user must review and approve the draft before any release is created. | ||
|
|
||
| ## Context | ||
|
|
||
| The `dotnet/extensions` repository ships NuGet packages across many functional areas (AI, HTTP Resilience, Diagnostics, Compliance, Telemetry, etc.). Releases come in two forms: | ||
|
|
||
| - **Monthly full releases** — all packages ship together with a minor version bump (e.g. v10.3.0 → v10.4.0) | ||
| - **Intra-month patch releases** — a targeted subset of packages ships with a patch version bump (e.g. v10.3.1), typically addressing specific bug fixes or urgent changes | ||
|
|
||
| The repository does not follow Semantic Versioning. Major versions align with annual .NET releases, minor versions increment monthly, and patch versions are for intra-month fixes. | ||
|
|
||
| The repository makes heavy use of `[Experimental]` attributes. Experimental diagnostic IDs are documented in [`docs/list-of-diagnostics.md`](../../docs/list-of-diagnostics.md). Breaking changes to experimental APIs are expected and acceptable. Graduation of experimental APIs to stable is a noteworthy positive event. | ||
|
|
||
| The repository uses `release/` branches (e.g. `release/10.4`) where release tags are associated with commits on those branches. When determining the commit range for a release, ensure the previous and target tags are resolved against the appropriate release branch history. | ||
|
|
||
| ## Execution Guidelines | ||
|
|
||
| - **Do not write intermediate files to disk.** Use the **SQL tool** for structured storage and querying (see [references/sql-storage.md](references/sql-storage.md) for schema). | ||
| - **Do not run linters, formatters, or validators** on the output. | ||
| - **Maximize parallel tool calls.** Fetch multiple PR and issue details in a single response. | ||
| - **Package assignment is file-path-driven.** Determine which packages a PR affects by examining which `src/Libraries/{PackageName}/` paths it touches. See [references/package-areas.md](references/package-areas.md) for the mapping. Use `area-*` labels only as a fallback. | ||
|
|
||
| ## Process | ||
|
|
||
| Work through each step sequentially. Present findings at each step and get user confirmation before proceeding. | ||
|
|
||
| ### Step 1: Determine Release Scope | ||
|
|
||
| The user may provide: | ||
| - **Two tags** (previous and target) — use these directly | ||
| - **A target tag only** — determine the previous release from `gh release list --repo dotnet/extensions --exclude-drafts` | ||
| - **No context** — show the last 5 published releases and ask the user to select | ||
|
|
||
| Once the range is established: | ||
|
|
||
| 1. Determine if this is a **full release** (minor version bump) or **patch release** (patch version bump) based on the version numbers. | ||
| 2. For patch releases, ask the user which packages are included (or infer from the PRs). | ||
| 3. Get the merge date range for PR collection. | ||
|
|
||
| ### Step 2: Collect and Enrich PRs | ||
|
|
||
| Follow [references/collect-prs.md](references/collect-prs.md): | ||
|
|
||
| 1. Search for merged PRs in the date range between the two tags. | ||
| 2. For each PR, fetch the file list and assign packages based on `src/Libraries/{PackageName}/` paths. | ||
| 3. Enrich with full PR body, reactions, linked issues, and co-author data. | ||
| 4. Apply exclusion filters (backports, automated version bumps, etc.). | ||
| 5. Mark remaining PRs as candidates. | ||
|
|
||
| Store all data using the SQL tool. | ||
|
|
||
| ### Step 3: Categorize and Group | ||
|
|
||
| Follow [references/categorize-entries.md](references/categorize-entries.md): | ||
|
|
||
| 1. **Assign categories**: What's Changed, Documentation Updates, Test Improvements, or Repository Infrastructure Updates. | ||
| 2. **Group by package area**: For "What's Changed" entries, group under descriptive area headings from [references/package-areas.md](references/package-areas.md). Each area heading must clearly identify the packages it covers. | ||
| 3. **Order by impact**: Within each area, order entries by impact — breaking changes first, then new features, then bug fixes. | ||
| 4. **Order areas by activity**: Place the area with the most entries first. | ||
|
|
||
| ### Step 4: Audit Experimental API Changes | ||
|
|
||
| Follow [references/experimental-features.md](references/experimental-features.md): | ||
|
|
||
| 1. For each candidate PR, **fetch the file list and diff** to identify changes to `[Experimental]` APIs. Do not infer experimental changes from PR titles — always verify against the actual files changed. | ||
| 2. Classify each change: now stable, new experimental, breaking change to experimental, or removed. | ||
| 3. Derive the conceptual feature name from the actual types/members affected in the diff. | ||
| 4. Record in the `experimental_changes` SQL table. | ||
| 5. Present findings to the user for confirmation. | ||
|
|
||
| ### Step 5: Determine Package Versions | ||
|
|
||
| Build the package version information: | ||
|
|
||
| 1. For **full releases**: all packages ship at the same version. Note the version number but do not generate a per-package table — it would be repetitive with no value. | ||
| 2. For **patch releases**: build a table of only the affected packages and their version numbers. | ||
| 3. Present the version information to the user for confirmation. The user may adjust which packages are included in a patch release. | ||
|
|
||
| ### Step 6: Draft Release Notes | ||
|
|
||
| Compose the release notes following [references/format-template.md](references/format-template.md) and [references/editorial-rules.md](references/editorial-rules.md): | ||
|
|
||
| 1. **Preamble** — Optionally draft 2–3 sentences summarizing the release theme. Present the preamble options to the user using the `ask_user` tool, offering them the choice of: (a) one of the suggested preambles, (b) writing their own, or (c) skipping the preamble entirely. | ||
| 2. **Packages in this release** — for patch releases, the table of affected packages and versions from Step 5. For full releases, omit this table (all packages ship at the same version and listing them all adds no value). | ||
| 3. **Breaking Changes** — stable API breaks only (should be very rare). Include migration guidance. | ||
| 4. **Experimental API Changes** — from Step 4 results. Group by change type. Omit empty subsections. | ||
| 5. **What's Changed** — area-grouped entries from Step 3. Omit empty areas. | ||
| 6. **Documentation Updates** — chronological flat list. | ||
| 7. **Test Improvements** — chronological flat list. | ||
| 8. **Repository Infrastructure Updates** — chronological flat list. | ||
| 9. **Acknowledgements** — new contributors, issue reporters, PR reviewers. | ||
| 10. **Full Changelog** — link to the GitHub compare view. | ||
|
|
||
| Omit empty sections entirely. | ||
|
|
||
| ### Step 7: Review and Finalize | ||
|
|
||
| Present the complete draft to the user: | ||
|
|
||
| 1. The full release notes markdown | ||
| 2. Summary statistics (number of PRs, packages affected, areas covered) | ||
| 3. Any unresolved items (ambiguous PRs, missing package assignments) | ||
|
|
||
| After the user has reviewed and approved the draft, present the finalization options using the `ask_user` tool: | ||
| - **Create draft release** — create a GitHub release in draft state with the notes as the body | ||
| - **Save to private gist** — save the draft notes to a private GitHub gist for later use | ||
| - **Cancel** — discard the draft without creating anything | ||
|
|
||
| ## Edge Cases | ||
|
|
||
| - **PR spans categories**: Categorize by primary intent; read the title and description. | ||
| - **PR spans multiple areas**: Place under the most central area; mention cross-cutting nature in the description. | ||
| - **Copilot-authored PRs**: If the PR author is Copilot or a bot, check the `copilot_work_started` timeline event for the triggering user, then assignees, then the merger. See [references/editorial-rules.md](references/editorial-rules.md) for the full fallback chain. Never fabricate an attribution — always derive it from the PR data. | ||
| - **No breaking changes**: Omit the Breaking Changes section entirely. | ||
| - **No experimental changes**: Omit the Experimental API Changes section entirely. | ||
| - **No user-facing changes**: If all PRs are documentation, tests, or infrastructure, note this in the release notes. The release still proceeds — this repository ships monthly regardless. | ||
| - **Patch release with unclear scope**: Ask the user to confirm which packages are included. | ||
| - **No previous release**: If this is the first release under the current versioning scheme, gather all PRs from the beginning of the tag history. | ||
| - **Version mismatch**: If the tag version doesn't match the version in source files, flag the discrepancy. | ||
| - **Large release (100+ PRs)**: Break the enrichment step into parallel batches. Consider summarizing lower-impact areas more aggressively. | ||
| - **Cross-repo changes**: Some PRs may reference issues or changes in other repos (e.g. `dotnet/runtime`). Use full markdown links for cross-repo references. | ||
75 changes: 75 additions & 0 deletions
75
.github/skills/release-notes/references/categorize-entries.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| # Categorize Entries | ||
|
|
||
| Sort candidate PRs into sections and group them by package area for the release notes. | ||
|
|
||
| ## Step 1: Assign categories | ||
|
|
||
| For each candidate PR, assign one of these categories based on the primary intent: | ||
|
|
||
| | Category | Key | Content | | ||
| |----------|-----|---------| | ||
| | What's Changed | `changed` | Features, bug fixes, API improvements, performance, breaking changes | | ||
| | Documentation Updates | `docs` | PRs whose sole purpose is documentation | | ||
| | Test Improvements | `tests` | Adding, fixing, or improving tests | | ||
| | Repository Infrastructure Updates | `infra` | CI/CD, dependency bumps, version bumps, build system, skills | | ||
|
|
||
| **Decision rules:** | ||
| - If a PR modifies files under `src/Libraries/` or `src/Generators/` or `src/Analyzers/`, it is `changed` (even if it also touches docs or tests) | ||
| - If a PR **only** modifies files under `docs/`, XML doc comments, or README files, it is `docs` | ||
| - If a PR **only** modifies files under `test/`, it is `tests` | ||
| - If a PR **only** modifies `eng/`, `scripts/`, `.github/`, CI YAML files, or root config files, it is `infra` | ||
| - When a PR spans multiple categories, assign based on primary intent — read the title and description | ||
|
|
||
| Update the SQL record: | ||
| ```sql | ||
| UPDATE prs SET category = '<category>' WHERE number = <pr_number>; | ||
| ``` | ||
|
|
||
| ## Step 2: Group by package area | ||
|
|
||
| For PRs in the `changed` category, group them under their package area headings using the `pr_packages` table. Each area heading uses the descriptive name from [package-areas.md](package-areas.md). | ||
|
|
||
| **Area heading selection:** | ||
| - If a PR affects packages in a single area → place under that area | ||
| - If a PR affects packages in multiple areas → place under the area most central to the change, noting the cross-cutting nature in the description if relevant | ||
| - If a `changed` PR has no package assignment (rare — e.g. a cross-cutting change to `Directory.Build.props` that affects all packages) → place under a "Cross-Cutting Changes" heading | ||
|
|
||
| **Area ordering in the release notes:** | ||
| Order areas by the number of entries (most active area first), then alphabetically for ties. This naturally highlights the areas with the most changes. | ||
|
|
||
| ## Step 3: Impact tiering within areas | ||
|
|
||
| Within each area, order entries by impact: | ||
|
|
||
| 1. **Breaking changes** (stable API breaks — should be very rare) | ||
| 2. **Experimental API changes** (graduated, removed, breaking — see [experimental-features.md](experimental-features.md)) | ||
| 3. **New features and significant improvements** | ||
| 4. **Bug fixes with community signal** (reported by community members, high reaction count) | ||
| 5. **Other bug fixes and improvements** | ||
|
|
||
| Use the popularity score from the SQL `prs` + `issues` tables (combined reaction counts) as a tiebreaker within each tier. | ||
|
|
||
| ## Step 4: Handle documentation, test, and infrastructure categories | ||
|
|
||
| These categories are **not** grouped by package area. They appear as flat lists in their own sections at the bottom of the release notes: | ||
|
|
||
| - **Documentation Updates** — sorted by merge date | ||
| - **Test Improvements** — sorted by merge date | ||
| - **Repository Infrastructure Updates** — sorted by merge date | ||
|
|
||
| ## Full vs. patch release considerations | ||
|
|
||
| ### Full monthly release | ||
| - All areas with changes get their own heading | ||
| - All four category sections appear (omit empty ones) | ||
| - Include the "Experimental API Changes" section if any experimental changes were detected | ||
|
|
||
| ### Targeted patch release | ||
| - Only the affected areas appear (typically 1–3 areas) | ||
| - The preamble explicitly states which packages are included in the patch | ||
| - The "Experimental API Changes" section still appears if relevant | ||
| - Documentation, test, and infrastructure sections may be shorter or absent | ||
|
|
||
| ## Multi-faceted PRs | ||
|
|
||
| A single PR may deliver a feature, fix bugs, AND improve performance. Use the verbatim PR title as the entry description regardless. Read the full PR description, not just the title, to determine the correct category assignment. |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.