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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions .github/skills/prepare-release/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
---
name: prepare-release
description: Prepares the repository for an internal release branch. Use this when asked to "prepare for a release", "prepare internal release branch", or similar release preparation tasks.
---

# Prepare Internal Release Branch

When preparing a public branch for internal release, apply the following changes:

## 1. Directory.Build.props

Add NU1507 warning suppression after the `TestNetCoreTargetFrameworks` PropertyGroup. Internal branches don't use package source mapping due to internal feeds:

```xml
<!-- Internal branches don't use package source mapping feature due to internal feeds, so disable NU1507 warning saying it should be used. -->
<PropertyGroup>
<NoWarn>$(NoWarn);NU1507</NoWarn>
</PropertyGroup>
```

Insert this new PropertyGroup right after the closing `</PropertyGroup>` that contains `TestNetCoreTargetFrameworks`.

## 2. NuGet.config

Remove the entire `<packageSourceMapping>` section. This section looks like:

```xml
<!-- Define mappings by adding package patterns beneath the target source.
https://aka.ms/nuget-package-source-mapping -->
<packageSourceMapping>
<packageSource key="dotnet-public">
<package pattern="*" />
</packageSource>
<packageSource key="dotnet-eng">
<package pattern="*" />
</packageSource>
<!-- ... more packageSource entries ... -->
</packageSourceMapping>
```

**Important**: Do NOT add new internal feed sources to NuGet.config - those are managed by Dependency Flow automation and will be added automatically.

## 3. eng/Versions.props

Update these two properties (do NOT change any version numbers):

Change `StabilizePackageVersion` from `false` to `true`:
```xml
<StabilizePackageVersion Condition="'$(StabilizePackageVersion)' == ''">true</StabilizePackageVersion>
```

Change `DotNetFinalVersionKind` from empty to `release`:
```xml
<DotNetFinalVersionKind>release</DotNetFinalVersionKind>
```

## 4. eng/pipelines/templates/BuildAndTest.yml

### Add Private Feeds Credentials Setup

After the Node.js setup task (the `NodeTool@0` task), add these two tasks to authenticate with private Azure DevOps feeds:

```yaml
- task: PowerShell@2
displayName: Setup Private Feeds Credentials
condition: eq(variables['Agent.OS'], 'Windows_NT')
inputs:
filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.ps1
arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config -Password $Env:Token
env:
Token: $(dn-bot-dnceng-artifact-feeds-rw)

- task: Bash@3
displayName: Setup Private Feeds Credentials
condition: ne(variables['Agent.OS'], 'Windows_NT')
inputs:
filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh
arguments: $(Build.SourcesDirectory)/NuGet.config $Token
env:
Token: $(dn-bot-dnceng-artifact-feeds-rw)
```

### Comment Out Integration Tests

Comment out the integration tests step as they require authentication to private feeds that isn't available during internal release builds:

```yaml
- ${{ if ne(parameters.skipTests, 'true') }}:
# Skipping integration tests for now as they require authentication to the private feeds
# - script: ${{ parameters.buildScript }}
# -integrationTest
# -configuration ${{ parameters.buildConfig }}
# -warnAsError 1
# /bl:${{ parameters.repoLogPath }}/integration_tests.binlog
# $(_OfficialBuildIdArgs)
# displayName: Run integration tests
```

## 5. azure-pipelines.yml

Remove the `codecoverage` stage entirely. This is the stage that:
- Has `displayName: CodeCoverage`
- Downloads code coverage reports from build jobs
- Merges and validates combined test coverage
- Contains a `CodeCoverageReport` job

Also remove the `codecoverage` dependency from the post-build validation's `validateDependsOn` list:

```yaml
# Remove this conditional dependency block:
- ${{ if eq(parameters.runTests, true) }}:
- codecoverage
```

## Files NOT to modify

- **eng/Version.Details.xml**: Version updates are managed by Dependency Flow automation
- **eng/Versions.props version numbers**: Package versions are managed by Dependency Flow automation
- **NuGet.config feed sources**: Internal darc feeds are added automatically by Dependency Flow

## Summary

| File | Action |
|------|--------|
| Directory.Build.props | Add `NU1507` to `NoWarn` in new PropertyGroup |
| NuGet.config | Remove entire `<packageSourceMapping>` section |
| eng/Versions.props | Set `StabilizePackageVersion=true`, `DotNetFinalVersionKind=release` |
| eng/pipelines/templates/BuildAndTest.yml | Add private feeds credentials setup tasks, comment out integration tests |
| azure-pipelines.yml | Remove `codecoverage` stage and its post-build dependency |
132 changes: 132 additions & 0 deletions .github/skills/release-notes/SKILL.md
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/*', 'sql', 'ask_user']
---

# 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 .github/skills/release-notes/references/categorize-entries.md
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.
Loading
Loading