Skip to content

Commit 99478fd

Browse files
jeffhandleyCopilotCopilot
authored
Add a Release-Notes skill (#7390)
* Add release-notes skill initial implementation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Revise release-notes skill based on v10.4.0 experience - Objective tone: avoid superlatives, favor factual descriptions - Preamble is optional with user choice via ask_user - Release branch-aware dedup: fetch release/ branches, check both tag and branch HEAD - Dynamic remote detection instead of hardcoded 'origin' - Attribution must come from stored PR data, never fabricated - Copilot-authored PR fallback chain: timeline event → assignees → merger - Co-author trailers collected from all PR commits, not just merge commit - Experimental audit requires file diff inspection, not title inference - No attributions in Experimental API Changes section - PR reviewer acknowledgements via get_reviews (excluding bots/authors) - Finalization options: draft release, private gist, or cancel - Diagnostic ID table removed; references docs/list-of-diagnostics.md - SQL schema adds pr_reviewers table Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Apply suggestions from Copilot review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Add pr_coauthors table and use it for acknowledgements - Add pr_coauthors table to store Co-authored-by trailer data - Add all-contributors query that unions PR authors and co-authors for new-contributor detection in acknowledgements - Update reviewer acknowledgements query to exclude co-authors - Add usage note for populating pr_coauthors during enrichment Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 6bfd8ca commit 99478fd

8 files changed

Lines changed: 1028 additions & 0 deletions

File tree

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
---
2+
name: release-notes
3+
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.'
4+
agent: 'agent'
5+
tools: ['github/*', 'sql', 'ask_user']
6+
---
7+
8+
# Release Notes
9+
10+
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.
11+
12+
> **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.
13+
14+
## Context
15+
16+
The `dotnet/extensions` repository ships NuGet packages across many functional areas (AI, HTTP Resilience, Diagnostics, Compliance, Telemetry, etc.). Releases come in two forms:
17+
18+
- **Monthly full releases** — all packages ship together with a minor version bump (e.g. v10.3.0 → v10.4.0)
19+
- **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
20+
21+
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.
22+
23+
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.
24+
25+
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.
26+
27+
## Execution Guidelines
28+
29+
- **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).
30+
- **Do not run linters, formatters, or validators** on the output.
31+
- **Maximize parallel tool calls.** Fetch multiple PR and issue details in a single response.
32+
- **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.
33+
34+
## Process
35+
36+
Work through each step sequentially. Present findings at each step and get user confirmation before proceeding.
37+
38+
### Step 1: Determine Release Scope
39+
40+
The user may provide:
41+
- **Two tags** (previous and target) — use these directly
42+
- **A target tag only** — determine the previous release from `gh release list --repo dotnet/extensions --exclude-drafts`
43+
- **No context** — show the last 5 published releases and ask the user to select
44+
45+
Once the range is established:
46+
47+
1. Determine if this is a **full release** (minor version bump) or **patch release** (patch version bump) based on the version numbers.
48+
2. For patch releases, ask the user which packages are included (or infer from the PRs).
49+
3. Get the merge date range for PR collection.
50+
51+
### Step 2: Collect and Enrich PRs
52+
53+
Follow [references/collect-prs.md](references/collect-prs.md):
54+
55+
1. Search for merged PRs in the date range between the two tags.
56+
2. For each PR, fetch the file list and assign packages based on `src/Libraries/{PackageName}/` paths.
57+
3. Enrich with full PR body, reactions, linked issues, and co-author data.
58+
4. Apply exclusion filters (backports, automated version bumps, etc.).
59+
5. Mark remaining PRs as candidates.
60+
61+
Store all data using the SQL tool.
62+
63+
### Step 3: Categorize and Group
64+
65+
Follow [references/categorize-entries.md](references/categorize-entries.md):
66+
67+
1. **Assign categories**: What's Changed, Documentation Updates, Test Improvements, or Repository Infrastructure Updates.
68+
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.
69+
3. **Order by impact**: Within each area, order entries by impact — breaking changes first, then new features, then bug fixes.
70+
4. **Order areas by activity**: Place the area with the most entries first.
71+
72+
### Step 4: Audit Experimental API Changes
73+
74+
Follow [references/experimental-features.md](references/experimental-features.md):
75+
76+
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.
77+
2. Classify each change: now stable, new experimental, breaking change to experimental, or removed.
78+
3. Derive the conceptual feature name from the actual types/members affected in the diff.
79+
4. Record in the `experimental_changes` SQL table.
80+
5. Present findings to the user for confirmation.
81+
82+
### Step 5: Determine Package Versions
83+
84+
Build the package version information:
85+
86+
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.
87+
2. For **patch releases**: build a table of only the affected packages and their version numbers.
88+
3. Present the version information to the user for confirmation. The user may adjust which packages are included in a patch release.
89+
90+
### Step 6: Draft Release Notes
91+
92+
Compose the release notes following [references/format-template.md](references/format-template.md) and [references/editorial-rules.md](references/editorial-rules.md):
93+
94+
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.
95+
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).
96+
3. **Breaking Changes** — stable API breaks only (should be very rare). Include migration guidance.
97+
4. **Experimental API Changes** — from Step 4 results. Group by change type. Omit empty subsections.
98+
5. **What's Changed** — area-grouped entries from Step 3. Omit empty areas.
99+
6. **Documentation Updates** — chronological flat list.
100+
7. **Test Improvements** — chronological flat list.
101+
8. **Repository Infrastructure Updates** — chronological flat list.
102+
9. **Acknowledgements** — new contributors, issue reporters, PR reviewers.
103+
10. **Full Changelog** — link to the GitHub compare view.
104+
105+
Omit empty sections entirely.
106+
107+
### Step 7: Review and Finalize
108+
109+
Present the complete draft to the user:
110+
111+
1. The full release notes markdown
112+
2. Summary statistics (number of PRs, packages affected, areas covered)
113+
3. Any unresolved items (ambiguous PRs, missing package assignments)
114+
115+
After the user has reviewed and approved the draft, present the finalization options using the `ask_user` tool:
116+
- **Create draft release** — create a GitHub release in draft state with the notes as the body
117+
- **Save to private gist** — save the draft notes to a private GitHub gist for later use
118+
- **Cancel** — discard the draft without creating anything
119+
120+
## Edge Cases
121+
122+
- **PR spans categories**: Categorize by primary intent; read the title and description.
123+
- **PR spans multiple areas**: Place under the most central area; mention cross-cutting nature in the description.
124+
- **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.
125+
- **No breaking changes**: Omit the Breaking Changes section entirely.
126+
- **No experimental changes**: Omit the Experimental API Changes section entirely.
127+
- **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.
128+
- **Patch release with unclear scope**: Ask the user to confirm which packages are included.
129+
- **No previous release**: If this is the first release under the current versioning scheme, gather all PRs from the beginning of the tag history.
130+
- **Version mismatch**: If the tag version doesn't match the version in source files, flag the discrepancy.
131+
- **Large release (100+ PRs)**: Break the enrichment step into parallel batches. Consider summarizing lower-impact areas more aggressively.
132+
- **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.
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# Categorize Entries
2+
3+
Sort candidate PRs into sections and group them by package area for the release notes.
4+
5+
## Step 1: Assign categories
6+
7+
For each candidate PR, assign one of these categories based on the primary intent:
8+
9+
| Category | Key | Content |
10+
|----------|-----|---------|
11+
| What's Changed | `changed` | Features, bug fixes, API improvements, performance, breaking changes |
12+
| Documentation Updates | `docs` | PRs whose sole purpose is documentation |
13+
| Test Improvements | `tests` | Adding, fixing, or improving tests |
14+
| Repository Infrastructure Updates | `infra` | CI/CD, dependency bumps, version bumps, build system, skills |
15+
16+
**Decision rules:**
17+
- 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)
18+
- If a PR **only** modifies files under `docs/`, XML doc comments, or README files, it is `docs`
19+
- If a PR **only** modifies files under `test/`, it is `tests`
20+
- If a PR **only** modifies `eng/`, `scripts/`, `.github/`, CI YAML files, or root config files, it is `infra`
21+
- When a PR spans multiple categories, assign based on primary intent — read the title and description
22+
23+
Update the SQL record:
24+
```sql
25+
UPDATE prs SET category = '<category>' WHERE number = <pr_number>;
26+
```
27+
28+
## Step 2: Group by package area
29+
30+
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).
31+
32+
**Area heading selection:**
33+
- If a PR affects packages in a single area → place under that area
34+
- 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
35+
- 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
36+
37+
**Area ordering in the release notes:**
38+
Order areas by the number of entries (most active area first), then alphabetically for ties. This naturally highlights the areas with the most changes.
39+
40+
## Step 3: Impact tiering within areas
41+
42+
Within each area, order entries by impact:
43+
44+
1. **Breaking changes** (stable API breaks — should be very rare)
45+
2. **Experimental API changes** (graduated, removed, breaking — see [experimental-features.md](experimental-features.md))
46+
3. **New features and significant improvements**
47+
4. **Bug fixes with community signal** (reported by community members, high reaction count)
48+
5. **Other bug fixes and improvements**
49+
50+
Use the popularity score from the SQL `prs` + `issues` tables (combined reaction counts) as a tiebreaker within each tier.
51+
52+
## Step 4: Handle documentation, test, and infrastructure categories
53+
54+
These categories are **not** grouped by package area. They appear as flat lists in their own sections at the bottom of the release notes:
55+
56+
- **Documentation Updates** — sorted by merge date
57+
- **Test Improvements** — sorted by merge date
58+
- **Repository Infrastructure Updates** — sorted by merge date
59+
60+
## Full vs. patch release considerations
61+
62+
### Full monthly release
63+
- All areas with changes get their own heading
64+
- All four category sections appear (omit empty ones)
65+
- Include the "Experimental API Changes" section if any experimental changes were detected
66+
67+
### Targeted patch release
68+
- Only the affected areas appear (typically 1–3 areas)
69+
- The preamble explicitly states which packages are included in the patch
70+
- The "Experimental API Changes" section still appears if relevant
71+
- Documentation, test, and infrastructure sections may be shorter or absent
72+
73+
## Multi-faceted PRs
74+
75+
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.

0 commit comments

Comments
 (0)