diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index d0262c28f9..5b3c85635a 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -81,6 +81,12 @@ git push origin [branch-name] - `release-notes/releases-index.json` - Master index of all .NET releases - `CONTRIBUTING.md` - Links to actual contribution guidelines in dotnet/runtime +### Copilot Skills + +This repository defines Copilot skills in `/.github/skills/`. Before performing any task, check if a matching skill exists and follow its process. Current skills: + +- `release-notes` - Generate .NET release notes for a preview or RC release (supports team-specific context) + ## Common Tasks ### Adding New Release Notes diff --git a/.github/skills/release-notes/SKILL.md b/.github/skills/release-notes/SKILL.md new file mode 100644 index 0000000000..fa71d7a93c --- /dev/null +++ b/.github/skills/release-notes/SKILL.md @@ -0,0 +1,113 @@ +--- +name: release-notes +description: Generate .NET release notes for a preview or RC release. Determines team context, gathers merged PRs, enriches with issue details, categorizes by impact, and produces formatted markdown. Use when asked to write, update, or draft release notes, a changelog, or a what's new summary for any .NET component. +compatibility: Requires GitHub MCP server or gh CLI, SQL tool for structured storage, and access to the dotnet/core repository clone. +disable-model-invocation: true +argument-hint: "[team] [owner/repo]" +--- + +# .NET Release Notes Generator + +Generate release notes for a .NET preview or RC release. This skill works for any .NET team that publishes release notes in the `dotnet/core` repository. + +## Execution guidelines + +- **Do not write intermediate files to disk.** Use the **SQL tool** for structured storage and querying (see [sql-storage.md](references/sql-storage.md) for schema). +- **Do not run linters, formatters, or validators.** Do not run markdownlint, prettier, link checkers, or any other validation tool on the output. The outputs of this skill are the release notes markdown file and validated code sample apps. +- **Maximize parallel tool calls.** Fetch multiple PR and issue details in a single response to minimize round trips. +- **Follow [GitHub tool guidance](references/github-tools.md)** for all GitHub API interactions. + +## Process + +### Step 1: Identify team and collect inputs + +**[Process inputs](references/process-inputs.md)** — determine which team's release notes are being produced, then collect preview name, Code Complete dates, and output path. + +Once the team is identified, load the team context from `references/team-.md`. The team context specifies: + +- Product name, component file, and repositories +- PR discovery approach (area labels, milestones, or other strategies) +- Content rules (what to include/exclude) +- Categorization guidance +- Community contributor details +- Release branch verification overrides +- Format overrides (document title, intro links, link format) +- Optional process steps (e.g., API diff review) +- Example release notes for reference + +Each process step below has a default approach defined in its reference file. **Team contexts can add to or override any step.** When a team context specifies an override, follow the team's instructions instead of (or in addition to) the defaults. + +Team contexts with defined references: + +| Team | Context file | Component file | +|------|-------------|----------------| +| Libraries | [team-libraries.md](references/team-libraries.md) | `libraries.md` | +| ASP.NET Core | [team-aspnetcore.md](references/team-aspnetcore.md) | `aspnetcore.md` | +| .NET SDK | [team-sdk.md](references/team-sdk.md) | `sdk.md` | + +Other teams can be added by creating a `references/team-.md` file following the same structure. + +### Step 2: Data pipeline + +Gather the changes included in the release: + +1. **[Collect and filter PRs](references/collect-prs.md)** — search for merged PRs using the team context's PR discovery approach (area labels, milestones, or other strategy). The team context overrides the default method when specified. +2. **[Enrich — fetch PR and issue details](references/enrich-prs.md)** — fetch full PR bodies, discover linked issues, gather reactions and Copilot summaries. +3. **API diff review** (optional) — if the team context specifies API diff review, follow [api-diff-review.md](references/api-diff-review.md) to cross-reference new APIs with candidate PRs. + +### Step 3: Verify scope + +Validate the candidate list: + +1. **[Deduplicate from previous release notes](references/dedup-previous-releases.md)** — ensure features aren't already covered in an earlier preview. Load the previous release notes for the team's component file (e.g., `libraries.md` for Libraries). **Retain these previous release notes in context** — they are needed during the authoring step for theme continuations. +2. **[Confirm inclusion in release branch](references/verify-release-branch.md)** — spot-check that candidate changes shipped in the target preview. Uses the VMR by default; team contexts can override the repo, branch pattern, and verification steps. + +### Step 4: Author content + +Write the release notes: + +1. **[Categorize entries by area, theme, and impact](references/categorize-entries.md)** — group PRs into impact tiers using common criteria plus any team-specific guidance from the team context. Reference the previous release notes (loaded during deduplication) to identify **theme continuations** — features that build on work from prior previews should acknowledge the earlier coverage and describe what's new. +2. **[Apply formatting rules](references/format-template.md)** — follow the standard .NET release notes document structure. Apply team context format overrides (document title, intro links, link format) when specified. +3. **[Apply editorial rules](references/editorial-rules.md)** — follow attribution, benchmark, naming, and ranking guidelines. Apply team context content rules (e.g., bug fix exclusions, PR link policy) when specified. + +### Step 5: Validate code samples + +**[Validate code samples](references/validate-samples.md)** — extract every code sample from the authored release notes, scaffold file-based .NET console apps in a `samples/` folder alongside the release notes file, and verify each sample compiles and runs. Fix any code samples in the release notes that fail validation (with user confirmation). A `.gitignore` at `release-notes/.gitignore` ensures the samples folders are not committed. + +### Step 6: Suggest reviewers + +**[Suggest reviewers](references/suggest-reviewers.md)** — gather authors, coauthors, assignees, and mergers from candidate PRs and present suggested reviewers grouped by area. + +### Step 7: Confirm and finalize + +Present the complete draft to the user: + +1. Feature list with categorization and ordering +2. Suggested reviewers grouped by area +3. Any unresolved items (ambiguous PRs, or for teams using API diff review, any unmatched API surface area) + +Get user confirmation before writing the output file. + +## Example usage + +**User prompt:** + +> Write the .NET Libraries release notes for .NET 11 Preview 2. The repo is dotnet/runtime. + +**Expected output:** A markdown file at `release-notes/11.0/preview/preview2/libraries.md` following the format: + +```markdown +# .NET Libraries in .NET 11 Preview 2 - Release Notes + +.NET 11 Preview 2 includes new .NET Libraries features & enhancements: + +- [Support for Zstandard compression](#support-for-zstandard-compression) +- [Faster time zone conversions](#faster-time-zone-conversions) +... + +## Support for Zstandard compression + +The new `ZstandardStream` class brings native Zstandard compression +support to `System.IO.Compression` ([dotnet/runtime#NNNNN](https://github.com/dotnet/runtime/pull/NNNNN)). +... +``` diff --git a/.github/skills/release-notes/references/api-diff-review.md b/.github/skills/release-notes/references/api-diff-review.md new file mode 100644 index 0000000000..2fbda5d716 --- /dev/null +++ b/.github/skills/release-notes/references/api-diff-review.md @@ -0,0 +1,65 @@ +# API Diff Review (Optional Step) + +> **This step is optional.** It applies only to teams whose team context specifies API diff review. Teams that produce components with significant public API surface (e.g., Libraries, WinForms, ASP.NET Core) benefit from cross-referencing new APIs with candidate PRs. + +## Locate the API diff + +Locate and load the API diff for the target release. The API diff provides context about which APIs were added or changed and significantly improves the quality of the generated release notes. + +The API diff lives under the `release-notes` folder within an `api-diff` subfolder for the target release. The team context specifies the exact path pattern. For example: +* .NET 11 Preview 1: `release-notes/11.0/preview/preview1/api-diff/Microsoft.NETCore.App/11.0-preview1.md` +* .NET 10 RC 2: `release-notes/10.0/preview/rc2/api-diff/Microsoft.NETCore.App/10.0-RC2.md` + +The API diff may not be available in the current branch yet. If the expected API diff path does not exist in the local clone, search for a pull request in `dotnet/core` that introduces the needed API diff: + +``` +search_pull_requests( + owner: "dotnet", + repo: "core", + query: "API diff " +) +``` + +If a PR with the API diff is found, fetch the diff files from that PR's branch. If no API diff is available from any source, warn the user and ask whether to proceed without it. + +## Load the API diff + +Once the API diff is located, load all of the API difference files under the appropriate subfolder. Read every diff file to understand the full set of APIs that have been added or changed in the release. + +## Cross-reference with candidate PRs + +After candidate PRs are collected (see [collect-prs.md](collect-prs.md)), cross-reference them against the new APIs. For each new API or namespace in the diff, verify that at least one candidate PR covers it. If an API in the diff has **no matching PR**, search for the implementing PR explicitly: + +``` +search_pull_requests( + owner: "", + repo: "", + query: "is:merged " +) +``` + +This catches PRs that were missed by the date range or that lacked a recognized area label. Add any discovered PRs to the candidate list. + +Also use the API diff to discover **issues** that drove new APIs. Many approved APIs originate from `api-approved` issues. Use `search_issues` to find related issues: + +``` +search_issues( + owner: "", + repo: "", + query: "label:api-approved " +) +``` + +If such issues exist, trace them to their implementing PRs and ensure those PRs are in the candidate list. + +## Unmatched API surface area + +After cross-referencing, if any substantial new APIs in the diff still cannot be correlated to a PR or issue, include a placeholder section in the release notes. Use a `**TODO**` marker so the author can manually resolve it later: + +```markdown +## + +**TODO:** The API diff shows new surface area for `` but the implementing PR/issue could not be found. Investigate and fill in this section. +``` + +Report these unmatched APIs during the [confirm and finalize](../SKILL.md) step so the user is aware. diff --git a/.github/skills/release-notes/references/categorize-entries.md b/.github/skills/release-notes/references/categorize-entries.md new file mode 100644 index 0000000000..22693d1b4d --- /dev/null +++ b/.github/skills/release-notes/references/categorize-entries.md @@ -0,0 +1,49 @@ +# Categorize Entries by Area, Theme, and Impact + +## Feature grouping + +Group related features under a **single top-level section** rather than scattering them as separate entries. Features that share a common initiative, theme, or parent issue should appear as subsections (`###`) under one heading (`##`). + +**Signals that features should be grouped:** +- They reference the same parent issue or initiative +- They are in the same namespace or closely related namespaces +- One feature is a prerequisite for another +- They would be confusing or redundant as separate TOC entries + +## Impact tiers + +Group PRs into tiers: + +- **Headline features**: New namespaces or types, implementations of new industry trends/algorithms, major new API surfaces +- **Quality**: PRs or groups of PRs that improve quality across an area +- **Performance**: PRs with benchmark data showing measurable improvements +- **Significant API additions**: Notable new API surface that unlocks new scenarios or provides meaningful productivity gains +- **Small improvements**: Single-mapping additions and minor fixes with public API changes should rarely be included +- **Preview feedback fixes**: Bug fixes or behavior changes made in response to community feedback on a previous preview. See [editorial-rules.md](editorial-rules.md#preview-to-preview-feedback-fixes) for inclusion criteria. These are ranked by the strength of community signal — an issue with 50+ reactions and active discussion is a headline-level entry, while one with minimal engagement is a minor mention + +Only Headline, Quality, Performance, and significant API additions go into the release notes. Use judgment — a 2-line dictionary entry addition is less noteworthy than a new numeric type. + +**Before assigning a tier**, check each candidate against the [partial features and building blocks](editorial-rules.md#partial-features-and-building-blocks) heuristics. If a candidate is part of a broader initiative, it may still deserve its own entry — the key question is whether a user can try it today. Features that are independently useful but part of a larger effort should note that context. Features that have no standalone value should be folded into a brief mention or omitted. + +The early previews (preview1 through preview5) tend to include more features, and the later previews (preview6, preview7, and rc1) tend to have fewer headline features and more quality improvements and small additions. The RC2 and GA releases typically have fewer changes so quality and performance improvements can be emphasized more. + +## Theme continuations + +Reference the previous release notes (loaded during [deduplication](dedup-previous-releases.md)) to identify features that build on work from prior previews. When a feature extends earlier work: + +- Acknowledge the earlier coverage briefly (e.g., "Building on the Zstandard support introduced in Preview 1...") +- Focus on what's **new** in this preview +- If the feature has evolved substantially, consider whether it warrants a fresh full write-up rather than just an update note + +## Multi-faceted PRs + +A single PR may span multiple categories — for example, a PR that rewrites an implementation may improve correctness, fix bugs, simplify the codebase, *and* deliver performance gains. Do not reduce such PRs to a single category. When writing the release notes entry, describe the full scope of the improvement. Read the full PR description, not just benchmark tables. + +## Team-specific categorization + +The team context may provide additional categorization guidance, such as: +- Specific example release notes to follow for style reference +- Additional tiers or groupings specific to the team's domain +- Guidance on how to handle certain types of changes (e.g., API review outcomes) + +Follow the team context's guidance when it extends or overrides these common rules. diff --git a/.github/skills/release-notes/references/collect-prs.md b/.github/skills/release-notes/references/collect-prs.md new file mode 100644 index 0000000000..7ad814eaa0 --- /dev/null +++ b/.github/skills/release-notes/references/collect-prs.md @@ -0,0 +1,79 @@ +# Collect and Filter PRs + +Pull merged PRs from the repositories specified in the team context. + +## Team-specific PR discovery + +**Before using the default approach below**, check the team context (`team-.md`) for a **PR Discovery** section. Teams may override the default approach entirely — for example, using milestones instead of labels, or different filtering criteria. + +If the team context specifies PR discovery overrides, follow those instructions instead of the default label-based approach below. The exclusion filters and data storage sections still apply regardless of the discovery method. + +## Default: Area-label-scoped search + +The default approach uses area labels defined in the team context to find relevant PRs. This works for teams that organize PRs by area label (e.g., `area-System.Collections`). + +### Primary — GitHub MCP server + +Use `search_pull_requests` with **label-scoped queries** to keep result sets small and avoid large responses being saved to temp files on disk. See [github-tools.md](github-tools.md) for response size guidance. + +Search for merged PRs one area label at a time, using the labels defined in the team context: + +``` +search_pull_requests( + owner: "", + repo: "", + query: "is:merged merged:.. label:", + perPage: 30 +) +``` + +Run label-scoped searches in **parallel batches** for efficiency. + +After the label-scoped searches, do a **catch-all search** for any remaining PRs that may use uncommon area labels. Use a broad query with the team's label prefix but keep `perPage` small: + +``` +search_pull_requests( + owner: "", + repo: "", + query: "is:merged merged:.. label:", + perPage: 30 +) +``` + +Page through results (incrementing `page`) until all PRs for each query are collected. Deduplicate by PR number across all queries before inserting into the database. + +**PRs without area labels.** Some PRs lack an area label altogether. To catch these, also run a search without label filters but restricted to the date range and `perPage: 30`. Check the title and description of unlabeled PRs for team-relevant content. If a PR references an issue (via "Fixes #..." links), fetch the issue to check for area labels. + +### Fallback — GitHub CLI + +If the GitHub MCP server is not available, use the `gh` CLI. Verify availability with `gh --version` first. + +```bash +REPO="/" # From team context + +gh pr list --repo "$REPO" --state merged \ + --search "merged:.." \ + --limit 1000 --json number,title,labels,author,mergedAt,url +``` + +For large date ranges, split into smaller windows to avoid hitting result limits. + +### Data storage + +Store all fetched PR data using the **SQL tool**. See [sql-storage.md](sql-storage.md) for the schema. Insert each PR into the `prs` table and use SQL queries for all subsequent filtering. + +## Filter to relevant PRs + +Apply these filters before marking PRs as candidates: + +### Exclusion filters + +- Labels: `backport`, `servicing`, `NO-MERGE` +- PRs whose title starts with `[release/` or contains `backport` +- PRs that are purely test, CI, or documentation changes (no `src` changes) + +### Team-specific filters + +Apply any additional filters specified in the team context (e.g., specific label inclusions/exclusions, path-based filtering). + +Mark matching PRs as candidates in the SQL `prs` table (`is_candidate = 1`). diff --git a/.github/skills/release-notes/references/dedup-previous-releases.md b/.github/skills/release-notes/references/dedup-previous-releases.md new file mode 100644 index 0000000000..c7e1fb7528 --- /dev/null +++ b/.github/skills/release-notes/references/dedup-previous-releases.md @@ -0,0 +1,46 @@ +# Verify: Deduplicate Against Previous Release Notes + +Before authoring content, check that candidate features have not already been covered in an earlier preview's release notes for the same major version. + +## Load prior release notes + +Load the team's component file (e.g., `libraries.md`, `aspnetcore.md`) from the immediately preceding release within the same major version. For example, when generating Preview 3, load Preview 2's notes; when generating RC1, load Preview 7's notes. + +When generating **Preview 1** release notes for a new major version, there are no prior previews to check. Instead, look back at the prior major version's late-cycle release notes — specifically RC1, RC2, and GA — since features that landed late in the previous release cycle may overlap with early work in the new version. For example, when generating .NET 12 Preview 1 notes, check: + +``` +release-notes/11.0/preview/rc1/.md +release-notes/11.0/preview/rc2/.md +release-notes/11.0/preview/ga/.md +``` + +These files are in the local repository clone under `release-notes//preview/`. + +**Retain the previous release notes in context** — they are needed in the [authoring step](categorize-entries.md) for identifying theme continuations. + +## Check for overlap + +For each candidate PR, check whether it (or its feature) already appears in a prior release's notes by looking for: + +- **PR number references** — search for `#` or the full PR URL in prior files +- **Feature names** — search for the API name, type name, or feature title + +Remove any PR from the candidate list whose feature is already covered. A PR that was merged in the date range of a prior preview but was not included in that preview's release notes may still be included — only exclude PRs whose features were actually written up. + +## Flag earlier PRs that survived dedup + +If any PRs were removed during dedup, review the remaining candidate PRs that were merged **before** the previous release's Code Complete date (i.e. PRs whose merge date falls in the earlier portion of the date range). These PRs were not found in the prior release notes but their merge dates suggest they *could* have been covered elsewhere. Present these PRs to the user and ask whether each should be included or excluded. For example: + +> The following PRs were merged before the .NET 11 Preview 1 Code Complete date but were **not** found in any prior release notes. They may have been intentionally omitted or covered in a different document. Please confirm whether to include them: +> +> - #12345 — `Add Foo.Bar overload` (merged 2025-11-15) +> - #12400 — `Optimize Baz serialization` (merged 2025-12-03) + +If no PRs were removed during dedup (i.e. nothing overlapped with prior notes), skip this sub-step — the earlier merge dates are expected given the date range and do not need user confirmation. + +## Handle cross-preview features + +Some features span multiple PRs across previews (e.g. a Preview 1 PR adds the core API and a Preview 2 PR extends it). In these cases: + +- If the new preview's PR is a **substantial extension** (new overloads, new scenarios, significant perf improvement on top of the original, or breaking changes to the API shape), include it as an update referencing the earlier work. Note the theme continuation for the [authoring step](categorize-entries.md). +- If the new preview's PR is a **minor follow-up** (bug fix, test addition, doc comment), skip it. diff --git a/.github/skills/release-notes/references/editorial-rules.md b/.github/skills/release-notes/references/editorial-rules.md new file mode 100644 index 0000000000..01d893be1c --- /dev/null +++ b/.github/skills/release-notes/references/editorial-rules.md @@ -0,0 +1,170 @@ +# Editorial Rules + +## Tone + +- Maintain a **positive tone** — highlight new benefits rather than expressing prior shortcomings + - ✅ `ProcessExitStatus provides a unified representation of how a process terminated.` + - ✅ `The new overloads extend TarFile.CreateFromDirectory to support all four tar formats.` +- When context about the prior state is needed, keep it brief and factual — one clause, not a paragraph — then pivot immediately to the new capability + +## Benchmarks + +- Use **exact data** from PR descriptions — never round, approximate, or paraphrase performance numbers +- State the benchmark scenarios (what was measured, what hardware, what workloads) +- Report speedup ranges only when the PR provides them explicitly and with sufficient context to make an accurate claim — do not extrapolate or generalize from partial data +- Include specific before/after measurements when they tell a compelling story (e.g. "dropped from 48.0 ns to 12.2 ns") +- Do **not** embed full BenchmarkDotNet tables in the release notes — summarize in prose +- If the user asks for exact tables, pull them verbatim from the PR body. Never reconstruct or approximate + +## Entry naming + +- Prefer a **brief description** of what the feature does over simply stating the API name. The heading should help a reader understand the value at a glance + - ✅ `## Support for Zstandard compression` + - ✅ `## Faster time zone conversions` + - ✅ `## Dictionary expression support for immutable and frozen collections` + - ❌ `## ZstandardStream` + - ❌ `## TimeZoneInfo performance` + - ❌ `## ImmutableDictionary.CreateRange` +- Keep headings concise — aim for 3–8 words +- Include the API or type name in the body text, not necessarily in the heading + +## Feature ranking + +Order features by **customer impact**, using both qualitative "wow" factor and quantitative popularity signals. Promote entries that affect popular, widely-used areas; move niche or specialized scenarios lower. + +**Primary ordering criteria** (biggest impact first): +1. Major new capabilities — especially those with high reaction counts on the backing issue or PR +2. Meaningful improvements to existing capabilities (performance, reliability, usability) +3. Smaller additions and fixes that round out the release + +**Popularity signals:** +- **Reaction counts**: PRs and issues with many 👍, ❤️, or 🚀 reactions indicate strong community demand. Use the combined reaction count across the PR and its linked issues as a tiebreaker within each tier +- **Linked issue upvotes**: An issue with 50+ reactions is a stronger signal than one with 2 + +## Community contributors + +Use the `community-contribution` label (or equivalent team-specific label) to identify PRs from external contributors. + +### Inline attribution + +When a documented feature was contributed by a community member, thank them inline at the end of that feature's section: + +```markdown +Thank you [@username](https://github.com/username) for this contribution! +``` + +### Community contributors section + +Include a "Community contributors" section at the bottom of the release notes listing ALL external contributors for the release — not just those who contributed documented features. This includes contributors whose PRs were bug fixes, test improvements, or other changes not covered in the release notes. + +To build this list, search for all merged PRs with the `community-contribution` label within the release's date range (or milestone, per the team context). List contributors alphabetically with links to their relevant PRs: + +```markdown +## Community contributors + +Thank you contributors! ❤️ + +- [@username](https://github.com///pulls?q=is%3Apr+is%3Amerged++author%3Ausername) +``` + +The link query format depends on the team context (e.g., milestone-based for ASP.NET Core, date-range-based for Libraries). + +## Inclusion criteria + +Include a feature if it gives users something new to try, something that works better, or something they asked for. Good signals: +- New capabilities users can take advantage of +- Measurable improvements to performance, reliability, or usability +- High community demand (reaction counts on backing issues) +- Behavior changes users need to be aware of + +### Preview-to-preview feedback fixes + +Bug fixes are generally excluded from release notes — fixing existing functionality is assumed. However, **preview-to-preview feedback fixes** are an important exception. These are changes made in response to community feedback on a previous preview, and they demonstrate that the preview process is working as intended. + +**Include a bug fix or behavior change when ALL of these apply:** + +1. **Preview-era issue** — the linked issue was created *after* the previous preview shipped (within the current release's preview cycle) +2. **Community-reported** — the issue was filed by someone outside the team (not the PR author or a regular contributor to the repo) +3. **Responsive fix** — a PR in the current preview directly addresses the reported issue + +**Prioritization signals** (more signal = more noteworthy): + +- **Reaction count on the issue** — an issue with many 👍 or other reactions indicates broad community impact +- **Comment activity** — issues with substantive discussion (not just "+1" comments) suggest the problem was significant +- **Multiple reporters** — if several issues report the same underlying problem, consolidate and note the breadth of feedback +- **Behavioral change** — fixes that change an API's behavior, defaults, or error handling based on feedback are especially worth calling out, since users who adopted the previous preview behavior need to know + +**How to write these entries:** + +- Frame them positively — "Based on community feedback, X now does Y" — not as admissions of mistakes +- Credit the reporter with a link to the issue +- Briefly describe what changed and why, so users on the previous preview know what to expect + +Exclude: +- Internal refactoring with no user-facing change +- Test-only changes +- Build/infrastructure changes +- Backports from servicing branches + +### Bug fix summary + +Bug fixes excluded from individual feature entries still deserve acknowledgment — they represent real quality improvements and often address issues reported by community members. Include a **"Bug fixes"** section after all feature entries (but before "Community contributors") that briefly lists the areas that received fixes. + +**How to build the summary:** + +1. Collect all candidate PRs that were excluded from feature entries because they are bug fixes, correctness improvements, or quality changes without new API surface. +2. Group them by area using the team context's grouping strategy (see below). +3. For each area, list the fixes. If any fix has a **community-reported backing issue** (the linked issue was filed by someone outside the team), call it out — this signals that the team is responsive to community feedback. + +**Grouping strategy:** + +The bug fix section uses a **nested list** — top-level bullets are area groups, with individual fixes as indented sub-bullets. How fixes are grouped depends on the team context: + +- **Default**: Group by namespace or component (e.g., "System.Net.Http", "System.Collections"). Multiple fixes in the same namespace share a single top-level bullet. +- Team contexts can override the grouping strategy (e.g., by product area like "Blazor", "Kestrel") — see the team context file for details. + +**Format:** + +```markdown +## Bug fixes + +This release includes bug fixes and quality improvements across several areas: + +- **System.Net.Http** + - Fixed authenticated proxy credential handling ([dotnet/runtime#123363](https://github.com/dotnet/runtime/issues/123363), reported by [@username](https://github.com/username)) + - Fixed edge-case non-ASCII host handling in HTTP logic ([dotnet/runtime#123934](https://github.com/dotnet/runtime/pull/123934)) +- **System.Collections** + - Fixed integer overflow in `ImmutableArray` range validation ([dotnet/runtime#124042](https://github.com/dotnet/runtime/pull/124042)) +- **System.Xml** + - Fixed `XDocument.LoadAsync` to avoid synchronous reads +``` + +Each area is a top-level bold bullet, with every fix as an indented sub-bullet — even if there is only one fix in that area. + +**Rules:** + +- Area name in bold at the top level +- Brief description of what was fixed, with PR link +- When a fix has a community-reported backing issue, include a link to the issue and credit the reporter inline +- Order areas alphabetically for consistency +- Do not include test-only, CI, doc-only, or infra changes — only fixes that improve user-facing behavior or correctness +- This section does NOT appear in the TOC — it's a lightweight summary, not a feature entry + +### Partial features and building blocks + +Some PRs contribute to a broader initiative where the full feature spans multiple previews. These still deserve coverage when they're independently useful — **err on the side of including** a feature if it's questionable. However, watch for building blocks that have no standalone value yet. + +**Warning signs to investigate** (none of these alone means "exclude" — use them to trigger closer inspection): + +1. **No meaningful code sample** — if you cannot write a code sample where a user does something useful with the feature, it's likely not independently usable yet. The [code sample validation step](validate-samples.md) is the final safety net, but check proactively during categorization. +2. **PR says "Contributes to" rather than "Fixes"** — this indicates the PR is one piece of a larger effort. Check the parent issue to see how much of the full API surface has shipped versus what's still pending. Many usable features "contribute to" a broad epic — this is a signal to investigate, not to exclude. +3. **No independent utility** — the change only becomes useful in combination with other changes that haven't shipped yet. Ask: can a user benefit from this change on its own, or does it require an unshipped API, configuration surface, or integration point to be meaningful? +4. **Release notes text says "upcoming" or "future"** — if the entry has to refer to planned-but-unshipped APIs to explain the feature's value, the feature may not be self-contained enough to document on its own. + +**The key question is always: can a user try this today?** If yes, include it — even if it's part of a larger initiative. When a feature IS part of a broader effort, note that context so readers understand the bigger picture (e.g., "This is part of the new ChildProcess API initiative; additional capabilities will follow in future previews."). + +**When a building block genuinely has no standalone value:** + +- If the parent initiative has a section in the release notes, mention the building blocks briefly as foundational work without giving them their own subsection. +- If no broader context exists, omit them entirely — they'll be covered when the full feature ships. +- When in doubt, include it with appropriate context rather than omitting it. diff --git a/.github/skills/release-notes/references/enrich-prs.md b/.github/skills/release-notes/references/enrich-prs.md new file mode 100644 index 0000000000..9f3578c8a4 --- /dev/null +++ b/.github/skills/release-notes/references/enrich-prs.md @@ -0,0 +1,137 @@ +# Enrich — Fetch PR and Issue Details + +For each candidate PR, fetch the full body (description) which contains benchmark data, API signatures, and motivation. Then fetch the details for issues referenced by or linked to the pull request — especially any issues resolved by the PR. + +## Fetch PR details — GitHub MCP server (primary) + +Use `pull_request_read` with method `get` to fetch each PR's full details: + +``` +pull_request_read( + method: "get", + owner: "", + repo: "", + pullNumber: +) +``` + +Multiple independent PR reads can be issued in parallel for efficiency. The PR response includes a `reactions` object with counts for each reaction type. Record the **total reaction count** for each PR as a popularity signal. + +After fetching PR details, also fetch the PR's comments to look for **Copilot-generated summaries**: + +``` +pull_request_read( + method: "get_comments", + owner: "", + repo: "", + pullNumber: +) +``` + +Look for comments authored by `copilot[bot]` or `github-actions[bot]` that contain a summary of the PR. These summaries are especially useful for large PRs where the description is auto-generated or sparse. + +## Populate reviewer data + +While fetching PR details, also collect contributor information for the [reviewer suggestion](suggest-reviewers.md) step: + +1. **PR author** — the `user.login` field from the PR details. +2. **PR assignees** — the `assignees` array from the PR details. +3. **PR merged-by** — the `merged_by` field. +4. **Coauthors from commits** — fetch the PR's merge commit and look for `Co-authored-by:` trailers in commit messages. + +Insert one row per contributor-role-PR combination into the `reviewers` table (see [sql-storage.md](sql-storage.md)). Exclude bot accounts and Copilot from all roles: + +- `Copilot`, `copilot-swe-agent[bot]`, `copilot[bot]` +- `dependabot[bot]`, `dotnet-maestro[bot]`, `github-actions[bot]` +- Any account whose login ends with `[bot]` + +## Discover related issues from the PR + +Use both methods to find issues that a PR resolves or references: + +### Parse the PR description for issue links + +Scan the PR body text for issue references: + +- **Closing keywords**: `Fixes #1234`, `Closes #1234`, `Resolves #1234` +- **Full URL links**: `https://github.com///issues/1234` +- **Cross-repo references**: `/#1234` +- **Bare hash references**: `#1234` (relative to the PR's repository) + +For Copilot-authored PRs, also look in the `
` / `Original prompt` collapsed section, which typically contains the original issue title, description, and a `Fixes` link. + +### Use the GitHub MCP server to find linked issues + +``` +search_issues( + owner: "", + repo: "", + query: "is:closed linked:pr reason:completed " +) +``` + +## Fetch issue details + +For each discovered issue number, use `issue_read` with method `get`: + +``` +issue_read( + method: "get", + owner: "", + repo: "", + issue_number: +) +``` + +Multiple independent issue reads can be issued in parallel. Record the **total reaction count** for each issue. Combine the PR and issue reaction counts to form an overall **popularity score** for each feature. Prioritize fetching issues that are: + +- Referenced by a `Fixes`/`Closes`/`Resolves` keyword +- Labeled `api-approved` (these contain approved API shapes and usage examples) +- Labeled `enhancement` with high reaction counts + +The issue body often contains richer context than the PR, including: +- **API proposals** with `### API Proposal` and `### API Usage` sections +- **Motivation** explaining why the feature was requested +- **Upvote counts** (via reactions) indicating community demand + +## Fallback — GitHub CLI + +If the GitHub MCP server is not available: + +```bash +gh pr view --repo "/" \ + --json number,title,body,labels,author,assignees,mergedAt,url + +gh issue view --repo "/" \ + --json number,title,body,labels,author,assignees,url +``` + +Store all fetched details using the **SQL tool** (update `body` and `reactions` columns in the `prs` table; insert into the `issues` table). Do **not** write intermediate files to disk. + +## Detect preview-to-preview feedback fixes + +After enriching all candidate PRs with their linked issues, scan for **preview feedback fixes** — bug fixes or behavior changes driven by community feedback on a previous preview. These are especially noteworthy for release notes (see [editorial-rules.md](editorial-rules.md#preview-to-preview-feedback-fixes)). + +### Identification heuristics + +For each candidate PR that has a linked issue (via `Fixes`/`Closes`/`Resolves`): + +1. **Check issue creation date** — if the issue was created *after* the start date (the previous preview's Code Complete), it's a preview-era issue. +2. **Check issue author** — if the author is NOT a member of the team (not in the PR author list, not a bot, and doesn't appear frequently as a merger/assignee across candidate PRs), flag it as community-reported. +3. **Check for bug/regression labels** — labels like `bug`, `regression`, `behavior-change`, or team-specific equivalents are strong signals. +4. **Check reaction and comment counts** — record these as the **community signal strength** for this fix. + +### Flag in the database + +For PRs that match, update the SQL record: + +```sql +UPDATE prs SET is_preview_feedback_fix = 1, + feedback_issue_number = , + feedback_issue_reactions = , + feedback_issue_comments = , + feedback_reporter = '' +WHERE number = ; +``` + +These flagged PRs are included during [categorization](categorize-entries.md) under the "Preview feedback fixes" tier and ranked by community signal strength. diff --git a/.github/skills/release-notes/references/format-template.md b/.github/skills/release-notes/references/format-template.md new file mode 100644 index 0000000000..6d03ac9453 --- /dev/null +++ b/.github/skills/release-notes/references/format-template.md @@ -0,0 +1,82 @@ +# Release Notes Format Template + +The release notes must mirror the style of the official .NET Preview release notes. + +## Document structure + +```markdown +# in .NET - Release Notes + +.NET includes new features & enhancements: + +- [Feature Name](#anchor) +- [Feature Name](#anchor) +... + + updates in .NET : + +- [What's new in .NET ](https://learn.microsoft.com/dotnet/core/whats-new/dotnet-/overview) documentation + +## Feature Name + + ([/#NNNNN](https://github.com///pull/NNNNN)). + +```csharp +// Code example or API signature +``` + +## Bug fixes + + + +## Community contributors + + +``` + +The `` name comes from the team context (e.g., ".NET Libraries", "ASP.NET Core", "Windows Forms"). + +## Issue and PR references + +Use the format `{org}/{repo}#{number}`. Always wrap references in markdown links that expand to the full `github.com` URL, since the release notes are published to a non-GitHub website where auto-linking is not available. + +- ✅ `[dotnet/runtime#124264](https://github.com/dotnet/runtime/pull/124264)` +- ✅ `[dotnet/runtime#118468](https://github.com/dotnet/runtime/issues/118468)` +- ❌ `dotnet/runtime#124264` (bare reference without markdown link) + +Link to PRs and issues naturally within the description text. Do not force them into a fixed position. + +## Section rules + +1. **TOC at top** — Every feature gets a linked entry in the table of contents +2. **One paragraph of context** — What the feature does and why it matters, with PR/issue links woven in naturally +3. **API signature** — Show the new public API surface in a `csharp` code block +4. **Usage example** — A short, runnable code snippet showing the feature in action +5. **Benchmark summary** (if applicable) — State what was measured and the speedup range. Do NOT embed full BenchmarkDotNet tables + +## Required content per feature + +Every feature entry MUST include: + +1. **Why** — What problem does this solve? What scenario does it enable? +2. **How** — A code sample showing how to use the feature. If a feature cannot be demonstrated with a code sample, reconsider whether it's user-facing enough for release notes. +3. **Learn more** — Link to the backing issue or PR (if one exists) for additional details. Do not clutter the release notes with links — only include issue/PR links when they provide meaningful context beyond what's already in the entry. (Note: some teams may omit PR links entirely; see the team context.) + +These requirements complement the structural section rules above. A well-written entry satisfies both the structural format and these content requirements. + +## Example section + +```markdown +## Finding Certificates By Thumbprints Other Than SHA-1 + +A new method on `X509Certificate2Collection` accepts the name of the hash algorithm to use +for thumbprint matching ([dotnet/runtime#NNNNN](https://github.com/dotnet/runtime/pull/NNNNN)). +Since SHA-2-256 and SHA-3-256 have the same lengths, matching any vaguely similar thumbprint +was not ideal. + +\```csharp +X509Certificate2Collection coll = store.Certificates.FindByThumbprint( + HashAlgorithmName.SHA256, thumbprint); +return coll.SingleOrDefault(); +\``` +``` diff --git a/.github/skills/release-notes/references/github-tools.md b/.github/skills/release-notes/references/github-tools.md new file mode 100644 index 0000000000..ef7c9961ae --- /dev/null +++ b/.github/skills/release-notes/references/github-tools.md @@ -0,0 +1,33 @@ +# GitHub Tool Usage Patterns + +Common guidance for interacting with GitHub data throughout the release notes pipeline. + +## Primary: GitHub MCP server + +Use the GitHub MCP server tools as the primary method for all GitHub API interactions. These tools provide structured data without requiring shell commands. + +## Fallback: GitHub CLI (`gh`) + +If the GitHub MCP server is unavailable, fall back to the `gh` CLI. Verify availability with `gh --version` first. + +## MCP response size management + +GitHub MCP search tools that return large payloads get saved to temporary files on disk — reading those files back requires PowerShell commands that trigger approval prompts. Prevent this by keeping individual search result sets small: + +- Use **label-scoped searches** (e.g. `label:area-System.Text.Json`) instead of fetching all merged PRs at once. +- Use `perPage: 30` or less for search queries. Only use `perPage: 100` for targeted queries that are expected to return few results. +- If a search response is saved to a temp file anyway, use the `view` tool (with `view_range` for large files) to read it — **never** use PowerShell/shell commands to read or parse these files. + +## Parallel fetching + +Multiple independent reads can be issued in parallel for efficiency: + +- Fetch multiple PR details in a single response +- Fetch multiple issue details in a single response +- Run label-scoped PR searches in parallel batches + +## Data storage + +Store all fetched data using the **SQL tool**. Do **not** write cache files to disk — disk I/O triggers approval prompts. Use SQL queries for all subsequent filtering, ranking, and reporting. + +See [sql-storage.md](sql-storage.md) for the common schema. diff --git a/.github/skills/release-notes/references/process-inputs.md b/.github/skills/release-notes/references/process-inputs.md new file mode 100644 index 0000000000..04efd05871 --- /dev/null +++ b/.github/skills/release-notes/references/process-inputs.md @@ -0,0 +1,43 @@ +# Process Inputs and Validate Readiness + +Collect all required inputs from the user and verify that prerequisite data is available before starting the data pipeline. + +## Identify the team + +If `$ARGUMENTS` is provided, parse it for the team name and optionally the repository (`owner/repo`). Otherwise, ask the user which team's release notes they are producing. + +Once the team is identified, load the team context from `team-.md`. The team context provides: + +- **Product name** — used in headings and descriptions +- **Repositories** — which repos to search for PRs +- **PR discovery** — how to find candidate PRs (area labels, milestones, or other strategy) +- **Content rules** — what to include/exclude (e.g., bug fix policy, PR link policy) +- **Categorization guidance** — team-specific tiers or groupings +- **Community contributor details** — team-specific query format +- **Release branch verification** — repo, branch pattern, and verification steps (if overriding VMR default) +- **Format overrides** — document title, intro links, link format +- **Optional steps** — e.g., whether API diff review applies +- **Example release notes** — paths to prior release notes for reference and style + +If no team context file exists for the specified team, inform the user and ask them to provide the equivalent configuration (product name, repos, labels) interactively. + +## Collect release inputs + +Collect inputs **one at a time** — ask a single question, wait for the answer, then ask the next. After each response, acknowledge what has been collected so far and ask for the next missing input: + +1. **Preview name** (e.g. ".NET 11 Preview 2") +2. **Start date** — ask: *"What was the Code Complete date for the previous release, ``?"* (ISO 8601). For **Preview 1**, this is the prior major version's RC1 Code Complete date (the vNext fork point); anything already covered in RC1/RC2/GA release notes will be de-duplicated in the [verify scope](dedup-previous-releases.md) step. +3. **End date** — ask: *"What was the Code Complete date for ``? (If it hasn't occurred yet, provide the expected date.)"* (ISO 8601) +4. **Output file** — path for the release notes markdown. Default: `release-notes//preview//.md` where `` comes from the team context. + +## Early validation + +If the team context specifies optional steps with prerequisites (e.g., API diff review requires diff files to be present), check for those prerequisites now. See the team context for details on what to check and where to find it. + +If any prerequisite is missing: + +- **Warn the user immediately**, specifying what is missing and the expected location. +- Explain the impact on quality (e.g., API diffs improve cross-referencing accuracy). +- Ask whether to proceed without it or wait until the prerequisite is available. + +Do not defer prerequisite checks to later pipeline steps — surface warnings as soon as inputs are collected so the user can decide early. diff --git a/.github/skills/release-notes/references/sql-storage.md b/.github/skills/release-notes/references/sql-storage.md new file mode 100644 index 0000000000..25146258e5 --- /dev/null +++ b/.github/skills/release-notes/references/sql-storage.md @@ -0,0 +1,107 @@ +# SQL Schema and Patterns + +Use the SQL tool for all structured data storage during the release notes pipeline. Do **not** write intermediate files to disk. + +## Core tables + +```sql +CREATE TABLE prs ( + number INTEGER PRIMARY KEY, + title TEXT, + author TEXT, + author_association TEXT, + labels TEXT, -- comma-separated label names + merged_at TEXT, + body TEXT, + reactions INTEGER DEFAULT 0, + is_library INTEGER DEFAULT 0, + is_candidate INTEGER DEFAULT 0, + is_preview_feedback_fix INTEGER DEFAULT 0, + feedback_issue_number INTEGER, + feedback_issue_reactions INTEGER, + feedback_issue_comments INTEGER, + feedback_reporter TEXT +); + +CREATE TABLE issues ( + number INTEGER PRIMARY KEY, + title TEXT, + body TEXT, + labels TEXT, + reactions INTEGER DEFAULT 0, + pr_number INTEGER -- the PR that references this issue +); + +CREATE TABLE reviewers ( + github_login TEXT NOT NULL, + role TEXT NOT NULL, -- 'author', 'assignee', 'merged_by', 'coauthor' + pr_number INTEGER NOT NULL, + area_labels TEXT, -- comma-separated area labels from the PR + PRIMARY KEY (github_login, role, pr_number) +); +``` + +## Common queries + +### Find candidate PRs + +```sql +SELECT * FROM prs WHERE is_candidate = 1 ORDER BY merged_at; +``` + +### Popularity ranking + +```sql +SELECT p.number, p.title, p.reactions, + COALESCE(SUM(i.reactions), 0) AS issue_reactions, + p.reactions + COALESCE(SUM(i.reactions), 0) AS total_reactions +FROM prs p +LEFT JOIN issues i ON i.pr_number = p.number +WHERE p.is_candidate = 1 +GROUP BY p.number +ORDER BY total_reactions DESC; +``` + +### PRs by area label + +```sql +SELECT * FROM prs +WHERE is_candidate = 1 + AND labels LIKE '%area-System.Text.Json%' +ORDER BY merged_at; +``` + +### Preview feedback fixes ranked by community signal + +```sql +SELECT p.number, p.title, p.feedback_reporter, + p.feedback_issue_number, p.feedback_issue_reactions, + p.feedback_issue_comments, + (p.feedback_issue_reactions + p.feedback_issue_comments) AS signal_strength +FROM prs p +WHERE p.is_candidate = 1 + AND p.is_preview_feedback_fix = 1 +ORDER BY signal_strength DESC; +``` + +### Reviewer suggestions by area + +```sql +SELECT + area_labels, + github_login, + COUNT(DISTINCT pr_number) AS pr_count, + GROUP_CONCAT(DISTINCT role) AS roles +FROM reviewers +WHERE github_login NOT LIKE '%[bot]%' + AND github_login != 'Copilot' +GROUP BY area_labels, github_login +ORDER BY area_labels, pr_count DESC, github_login; +``` + +## Usage notes + +- Insert PRs as they are discovered during collection. Update `body` and `reactions` during enrichment. +- Mark candidates with `is_candidate = 1` after filtering. +- Insert reviewer data during enrichment (see [suggest-reviewers.md](suggest-reviewers.md)). +- Additional PRs can be added to the candidate list manually by number. diff --git a/.github/skills/release-notes/references/suggest-reviewers.md b/.github/skills/release-notes/references/suggest-reviewers.md new file mode 100644 index 0000000000..ba9f7b597b --- /dev/null +++ b/.github/skills/release-notes/references/suggest-reviewers.md @@ -0,0 +1,75 @@ +# Suggest Reviewers + +After authoring the release notes, compile a list of suggested reviewers by analyzing the authors, coauthors, and reviewers of the candidate PRs that were included in the release notes. This helps the release notes author identify the right people to tag for reviewing specific sections. + +## Data sources + +For each candidate PR (those with `is_candidate = 1` in the `prs` table), gather contributor information from: + +1. **PR author** — the `user.login` field from the PR details (already fetched during [enrichment](enrich-prs.md)). +2. **PR assignees** — the `assignees` array from the PR details. Assignees are typically the area owner or tech lead who shepherded the PR. +3. **PR merged-by** — the `merged_by` field. The person who merged the PR is familiar with the changes. +4. **Coauthors from commits** — fetch the PR's merge commit (or the commits in the PR) and look for `Co-authored-by:` trailers in commit messages. Use `get_commit` with the PR's merge commit SHA, or `list_commits` on the PR's head branch, and parse trailer lines matching `Co-authored-by: Name `. + +## SQL schema + +Store reviewer data in the `reviewers` table (see [sql-storage.md](sql-storage.md)): + +```sql +INSERT INTO reviewers (github_login, role, pr_number, area_labels) +VALUES ('', '', , ''); +``` + +Insert one row per contributor-role-PR combination. A single person may appear multiple times across different roles and PRs. + +## Filtering + +Exclude bot accounts and Copilot from the reviewer list. This applies to all roles including coauthors: +- `Copilot`, `copilot-swe-agent[bot]`, `copilot[bot]` +- `dependabot[bot]`, `dotnet-maestro[bot]`, `github-actions[bot]` +- Any account whose login ends with `[bot]` + +## Aggregation + +Query the reviewers table to produce a summary grouped by area: + +```sql +SELECT + area_labels, + github_login, + COUNT(DISTINCT pr_number) AS pr_count, + GROUP_CONCAT(DISTINCT role) AS roles +FROM reviewers +WHERE github_login NOT LIKE '%[bot]%' + AND github_login != 'Copilot' +GROUP BY area_labels, github_login +ORDER BY area_labels, pr_count DESC, github_login; +``` + +## Presentation + +Present the suggested reviewers to the user as part of the confirmation step. Format as a grouped list: + +``` +## Suggested Reviewers + +Based on the PRs included in these release notes, the following people are most +familiar with the changes and well-suited to review specific sections: + +### Process APIs (System.Diagnostics.Process) +- @person1 — authored #124264, merged #124256 (2 PRs) +- @person2 — assigned on #124264 (1 PR) + +### System.Text.Json +- @person5 — authored #123940 +- @person6 — reviewed and merged #123940 +``` + +**Ranking within each area:** List contributors by the number of PRs they touched (descending), then alphabetically. People who appear in multiple roles (e.g. both author and reviewer) for the same area are stronger candidates. + +**Cross-area contributors:** If someone appears across 3+ areas, call them out separately as a potential overall reviewer: + +``` +### Overall Reviewers +- @person7 — involved in 4 PRs across Process APIs, System.Text.Json, and System.IO +``` diff --git a/.github/skills/release-notes/references/team-aspnetcore.md b/.github/skills/release-notes/references/team-aspnetcore.md new file mode 100644 index 0000000000..ca9bad1202 --- /dev/null +++ b/.github/skills/release-notes/references/team-aspnetcore.md @@ -0,0 +1,57 @@ +# ASP.NET Core Team Context + +Team-specific overrides for generating ASP.NET Core release notes. + +## PR Discovery + +**Overrides the default label-based approach** in [collect-prs.md](collect-prs.md). + +- **Repo**: `dotnet/aspnetcore` +- ASP.NET Core uses **milestones** (e.g., `11.0-preview2`) to organize PRs by release, not area labels. +- Use the `community-contribution` label to identify community contributor PRs. +- Community contributor search uses the milestone query: `?q=is%3Apr+is%3Amerged+milestone%3A+author%3Ausername` + +## Release Branch Verification + +**Overrides the default VMR verification** in [verify-release-branch.md](verify-release-branch.md). + +- **Repository**: `dotnet/aspnetcore` (not the VMR) +- **Branch pattern**: `release/.0-preview` (e.g., `release/11.0-preview2`) +- If a PR merged after the branch cut, look for a **backport PR** with the `Servicing-approved` label. If no backport exists, the feature slips to the next preview. + +## Content Rules + +### Bug fixes + +Include a **Bug fixes** section listing fixes grouped by **product area** (e.g., "Blazor", "Kestrel", "SignalR", "Identity", "IIS"), with each fix as an indented sub-bullet under the area. Credit community contributors inline. Order areas alphabetically. + +Example: + +```markdown +- **Blazor** + - Fixed `Label` component `id` attribute generation in interactive render mode ([dotnet/aspnetcore#65263](https://github.com/dotnet/aspnetcore/pull/65263)) + - Fixed `[EditorRequired]` warning incorrectly shown in SSR mode ([dotnet/aspnetcore#65393](https://github.com/dotnet/aspnetcore/pull/65393)) +- **Kestrel** + - Fixed request smuggling mitigation to use `TryAdd()` for `X-Content-Length` header ([dotnet/aspnetcore#65445](https://github.com/dotnet/aspnetcore/pull/65445)) +``` + +### Performance improvements + +Include a **Performance improvements** section for major, measurable performance wins (e.g., significant throughput improvements, large allocation reductions). Minor internal optimizations without measurable user impact should be omitted. + +## Feature Categorization + +Order sections by customer impact, using reaction counts on backing issues as a signal: + +- Blazor +- Minimal APIs / OpenAPI +- SignalR +- Identity / Security +- Kestrel / Server +- Templates / Tooling +- Observability + +## Format + +- **Document title**: `# ASP.NET Core in .NET - Release Notes` +- **Intro links**: Include links to the "What's new" docs page and the ASP.NET Core roadmap issue. diff --git a/.github/skills/release-notes/references/team-libraries.md b/.github/skills/release-notes/references/team-libraries.md new file mode 100644 index 0000000000..705e50c327 --- /dev/null +++ b/.github/skills/release-notes/references/team-libraries.md @@ -0,0 +1,65 @@ +# Libraries Team Context + +## Product + +- **Product name**: .NET Libraries +- **Component file**: `libraries.md` +- **Repository**: `dotnet/runtime` + +## PR Discovery + +Uses the default area-label-scoped approach from [collect-prs.md](collect-prs.md). Search for merged PRs using these area labels (run in parallel batches): + +- `area-System.Text.Json`, `area-System.Net.Http`, `area-System.Collections` +- `area-System.IO`, `area-System.IO.Compression`, `area-System.Threading` +- `area-System.Numerics`, `area-System.Runtime`, `area-System.Memory` +- `area-System.Security`, `area-System.Diagnostics`, `area-System.Globalization` +- `area-System.Linq`, `area-System.Reflection`, `area-System.Reflection.Emit` +- `area-System.Formats.*`, `area-System.Net.*`, `area-System.Text.*` +- `area-Microsoft.Extensions.*`, `area-Extensions-*` + +**Catch-all prefix**: `area-System` (to catch uncommon area labels) + +## Release Branch Verification + +Uses the default VMR verification from [verify-release-branch.md](verify-release-branch.md). + +- **VMR path**: `src/runtime/` + +## Optional steps + +- **API diff review**: Yes — follow [api-diff-review.md](api-diff-review.md). The API diff path pattern is `release-notes//preview//api-diff/Microsoft.NETCore.App/`. Cross-reference the API diff with candidate PRs after collection and use it to discover implementing PRs and `api-approved` issues. + +## Categorization guidance + +### Bug fix grouping + +Group bug fixes by their `area-` label (e.g., `area-System.Net.Http` → "System.Net.Http", `area-System.Collections` → "System.Collections"). When a PR has no `area-` label, use the library name instead. When multiple fixes share the same area, list them as indented sub-bullets under a shared top-level bullet. Order areas alphabetically. + +Example: + +```markdown +- **System.Collections** + - Fixed integer overflow in `ImmutableArray` range validation ([dotnet/runtime#124042](https://github.com/dotnet/runtime/pull/124042)) +- **System.Net.Http** + - Fixed authenticated proxy credential handling ([dotnet/runtime#123328](https://github.com/dotnet/runtime/pull/123328), reported by [@ptarjan](https://github.com/ptarjan)) + - Fixed edge-case non-ASCII host handling in HTTP logic ([dotnet/runtime#123934](https://github.com/dotnet/runtime/pull/123934)) +- **System.Numerics** + - Fixed `Vector2`/`Vector3` `EqualsAny` returning incorrect results due to hidden padding elements ([dotnet/runtime#123594](https://github.com/dotnet/runtime/pull/123594)) + - Fixed missing early returns in `TensorPrimitives.Round` causing double-rounding ([dotnet/runtime#124280](https://github.com/dotnet/runtime/pull/124280)) +``` + +### General categorization + +In addition to the common [categorization tiers](categorize-entries.md): + +- PRs labeled `community-contribution` from contributors with valuable features or quality improvements deserve extra consideration for inclusion +- Changes to widely-used libraries (`System.Text.Json`, `System.Net.Http`, `System.Collections`, `System.IO`, `System.Threading`) affect more users than changes to narrower namespaces — when two entries are otherwise similar in impact, prefer the one in the more widely-used library + +## Example release notes + +Use these as reference for style and depth: + +- `release-notes/11.0/preview/preview1/libraries.md` +- `release-notes/10.0/preview/preview1/libraries.md` +- `release-notes/9.0/preview/rc1/libraries.md` diff --git a/.github/skills/release-notes/references/team-sdk.md b/.github/skills/release-notes/references/team-sdk.md new file mode 100644 index 0000000000..4d52791975 --- /dev/null +++ b/.github/skills/release-notes/references/team-sdk.md @@ -0,0 +1,22 @@ +# .NET SDK Team Release Notes Context + +Team-specific overrides for generating .NET SDK release notes. + +## PR Discovery + +**Overrides the default label-based approach** in [collect-prs.md](collect-prs.md). + +- **Repo**: `dotnet/dotnet` +- focus on PRs that touch the `src/sdk` path, especially those that are codeflow-related or modify/revert SDK code directly in the VMR. + +## Content Rules + +use the strategies outlined in the dotnet/sdk's .github/skills/generate-release-notes for team-specific guidance on what to include, how to categorize, and how to format entries. + +## Sanity-checking PR candidates + +VMR branches are the final source of truth - use the VMR to determine candidate SDK PRs for inclusion, even if they don't have the expected labels or aren't linked to the expected milestones. Spot-check that candidate PRs actually shipped in the target preview by verifying their presence in the VMR branch for the preview or release selected. + +Once candidates are identified, cross-reference with the dotnet/sdk repo for PR details, linked issues, and design documents. + +When getting candidates, ensure that the changes are _only_ in this release - they should not have been included in previous previews. Use the previous release notes for the SDK to check for this, as well as the previous-release' VMR branch. \ No newline at end of file diff --git a/.github/skills/release-notes/references/validate-samples.md b/.github/skills/release-notes/references/validate-samples.md new file mode 100644 index 0000000000..c0c41230cc --- /dev/null +++ b/.github/skills/release-notes/references/validate-samples.md @@ -0,0 +1,112 @@ +# Validate Code Samples + +After authoring the release notes, extract all code samples and verify they compile and function correctly. This catches API typos, missing usings, and incorrect signatures before the release notes are published. + +## Process + +### 1. Set up the samples folder + +Determine the samples folder path as a `samples/` directory alongside the output file. For example, if the output file is `release-notes/11.0/preview/preview2/libraries.md`, the samples folder is `release-notes/11.0/preview/preview2/samples/`. + +Before creating any sample projects, ensure a `.gitignore` file exists at `release-notes/.gitignore` that excludes all samples folders. If the file does not exist or does not already contain the samples exclusion, create or update it with: + +``` +# Code sample validation apps created during release notes authoring +**/samples/ +.gitignore +``` + +### 2. Extract code samples + +Scan the authored release notes for fenced `csharp` code blocks. For each code block: + +1. **Identify the feature** — use the nearest preceding `##` heading as the feature name. +2. **Classify the snippet** — determine whether the snippet is: + - A **runnable example** — contains executable statements that can be wrapped in a console app (most common). + - An **API signature** — shows a type/method declaration only; not directly runnable but can be validated as compilable within a stub class. + - A **fragment** — incomplete code that requires surrounding context to compile (e.g., a lambda expression, a partial method body). These need wrapping in an appropriate context. + +### 3. Scaffold console apps + +For each feature with code samples, create a [file-based C# program](https://raw.githubusercontent.com/dotnet/docs/refs/heads/main/docs/csharp/fundamentals/tutorials/file-based-programs.md) in the samples folder. File-based programs are single `.cs` files that build and run directly with `dotnet .cs` — no project file required. + +``` +samples/ + .cs +``` + +**`.cs`**: Wrap the code sample in a single source file: + +```csharp +#:property PublishAot=false +// Sample validation for: +// Source: + + +``` + +The `#:property PublishAot=false` directive is required to ensure the installed SDK is used for building the apps instead of NativeAOT compilation. + +- For **runnable examples**: place the code as top-level statements. +- For **API signatures**: place the declaration inside a class and add top-level statements that reference the type to confirm it compiles. +- For **fragments**: wrap in the necessary context (class, method body, etc.) to make the code compilable. +- Add any required `using` directives that the snippet assumes but doesn't include. + +If the code sample depends on a NuGet package not included in the default SDK (common for `Microsoft.Extensions.*` or preview packages), add `#:package` directives at the top of the file: + +```csharp +#:package Microsoft.Extensions.Configuration@10.0.0-preview.* +``` + +If multiple code blocks for the same feature are logically sequential, combine them into a single `.cs` file. + +**Fallback to project-based apps**: If a sample cannot be validated as a file-based program (e.g., it requires multiple source files, custom MSBuild properties, or project-level configuration beyond what `#:package` supports), fall back to creating a traditional `.csproj` + `Program.cs` pair in a subfolder: + +``` +samples/ + / + .csproj + Program.cs +``` + +### 4. Build and run each sample + +For each sample: + +```bash +dotnet samples/.cs +``` + +The `dotnet` host builds and runs the file-based program in a single command. For project-based fallback samples, use `dotnet run --project samples//`. + +- If the build **succeeds** and the program runs without error, the sample is validated. + +- If the build **fails**, diagnose the error: + - **Missing using directive** — add it to the source file and retry. + - **Wrong API name or signature** — the release notes code sample is incorrect. Fix the code sample in the release notes and rebuild. + - **Missing package reference** — add a `#:package` directive (or a `` for project-based fallbacks) and retry. + - **Requires infrastructure not available locally** (e.g., network service, database, specific OS) — document that the sample was validated as compilable but could not be run. Move on. + +- If the run **throws an exception**, evaluate whether the exception is expected (e.g., a `FileNotFoundException` when no test file exists) or indicates a bug in the sample. Fix the release notes code sample if the error reveals an incorrect usage pattern. + +### 5. Report results + +After validating all samples, present a summary to the user: + +| Feature | Build | Run | Notes | +|---------|-------|-----|-------| +| Zstandard compression | ✅ | ✅ | | +| Faster time zone conversions | ✅ | ⚠️ | Expected exception: no tzdata in sandbox | +| ... | | | | + +For any sample that required changes to the release notes code, highlight the correction so the user can review it. + +### 6. Clean up + +The samples folder is excluded from git via the `.gitignore` created in step 1. Leave the samples in place so the user can inspect or re-run them, but they will not be committed. + +## Notes + +- **SDK availability**: The target .NET SDK version must be installed locally for the samples to build. Check with `dotnet --list-sdks`. If the required SDK is not installed, prompt the user to install a daily build from the [.NET SDK supported platforms builds table](https://github.com/dotnet/dotnet/blob/main/docs/builds-table.md#supported-platforms) — provide this link so they can download the appropriate installer for their platform. Explain that installing the daily build SDK will allow code samples to be validated against the actual build, then **ask the user for confirmation** before proceeding with validation. If the user declines the install, skip validation and note that samples were not verified. +- **Partial validation is acceptable**: Not every snippet can be a fully runnable app (e.g., ASP.NET middleware pipelines, GUI code). For these, validate that the code compiles even if it cannot be executed. +- **Do not modify release notes silently**: If a code sample needs correction, always show the user the original and corrected versions and get confirmation before updating the release notes file. diff --git a/.github/skills/release-notes/references/verify-release-branch.md b/.github/skills/release-notes/references/verify-release-branch.md new file mode 100644 index 0000000000..ccc3db9002 --- /dev/null +++ b/.github/skills/release-notes/references/verify-release-branch.md @@ -0,0 +1,74 @@ +# Verify: Confirm Inclusion in Release Branch + +After collecting and enriching candidates (including any manually added PRs), verify that candidate changes actually shipped in the target release. + +## Default: VMR verification + +By default, verify against the `dotnet/dotnet` Virtual Monolithic Repository (VMR), which contains all .NET source code. Its release branches represent what ships in each preview. + +## Team-specific overrides + +Some teams verify against their own repository instead of the VMR. **If the team context specifies a release branch override** (different repo, branch pattern, or verification steps), use those instead of the VMR defaults below. The team context takes precedence for: + +- **Repository** — which repo to check (e.g., `dotnet/aspnetcore` instead of `dotnet/dotnet`) +- **Branch pattern** — how the release branch is named (e.g., `release/.0-preview` instead of the VMR pattern) +- **Verification steps** — any team-specific process for confirming inclusion (e.g., checking for backport PRs) + +When team overrides apply, skip the VMR-specific sections below and follow the team context's instructions instead. + +## Determine the release branch name + +The expected branch name pattern is: + +``` +release/.0.1xx- +``` + +For example: +- .NET 11 Preview 1 → `release/11.0.1xx-preview1` +- .NET 11 Preview 2 → `release/11.0.1xx-preview2` +- .NET 11 RC 1 → `release/11.0.1xx-rc1` + +Use the GitHub MCP server (or CLI fallback) to verify the branch exists: + +``` +list_branches( + owner: "dotnet", + repo: "dotnet" +) +``` + +If the expected branch is **not found**, search for branches matching `release/.0*` and present the user with the matching branch names so they can select the correct one. + +## Spot-check that the newest changes are included + +Start from the most recently merged PRs in the candidate list and work backward. For each PR, verify its changes are present in the VMR release branch by either: + +1. **Searching for code** introduced by the PR in the `dotnet/dotnet` repo: + + ``` + search_code( + query: "repo:dotnet/dotnet path:src/ " + ) + ``` + + The `path` prefix depends on the team context — e.g., `src/runtime/` for Libraries and Runtime, `src/aspnetcore/` for ASP.NET Core. + +2. **Checking commit history** on the release branch for source code updates that post-date the PR merge: + + ``` + list_commits( + owner: "dotnet", + repo: "dotnet", + sha: "release/.0.1xx-", + perPage: 30 + ) + ``` + + Look for commits with messages like `"Source code updates from dotnet/"` dated after the PR's merge date. The dotnet-maestro bot regularly syncs changes from component repos into the VMR. + +Stop checking after **2 consecutive PRs are confirmed present** — if the two newest changes made it into the release branch, older changes are also included. + +If any change is **not found** in the release branch, inform the user that the feature may not have been included in this preview release. Suggest either: +- Moving that feature to the **next preview's** release notes +- Confirming with the release team whether a late sync occurred