Skip to content
Open
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
ef9876a
Use flat2 package lookup before attempting a search
jeffhandley Feb 8, 2026
b39b267
Infer CoreRepo parameter from git repo root
jeffhandley Feb 8, 2026
33251f0
Resolve CoreRepo and TmpFolder to absolute paths
jeffhandley Feb 8, 2026
d66ecc7
Default PreviousNuGetFeed to nuget.org
jeffhandley Feb 8, 2026
5b88e92
Rename PreviewOrRC to ReleaseKind and make PreviewNumberVersion optio…
jeffhandley Feb 8, 2026
929e7d4
Rename DotNetVersion to MajorMinor and PreviewNumberVersion to Previe…
jeffhandley Feb 8, 2026
99c4c5a
Make TmpFolder optional with auto-created temp directory
jeffhandley Feb 8, 2026
e86bc82
Auto-discover current version from NuGet feed
jeffhandley Feb 8, 2026
0da47ea
Auto-discover previous version from NuGet feed
jeffhandley Feb 8, 2026
867a104
Accept CurrentNuGetFeed as a positional parameter
jeffhandley Feb 8, 2026
ab1cd95
Rewrite RunApiDiff.md with full parameter documentation
jeffhandley Feb 8, 2026
b0c4ecf
Clarify ApiDiff tool install instructions
jeffhandley Feb 8, 2026
7e558bf
Clean up docs and examples
jeffhandley Feb 8, 2026
9a67bf2
Default CurrentNuGetFeed to nuget.org
jeffhandley Feb 8, 2026
2eea768
Combine ReleaseKind and PreviewRCNumber into PrereleaseLabel
jeffhandley Feb 8, 2026
236b77f
Rename PackageVersion to Version and extract MajorMinor/PrereleaseLab…
jeffhandley Feb 8, 2026
21b2271
Deduplicate version-parsing logic
jeffhandley Feb 8, 2026
30795b9
Move ParsePrereleaseLabel to the Functions section
jeffhandley Feb 8, 2026
9e7ce18
Remove dead RebuildIfExeNotFound function
jeffhandley Feb 8, 2026
349f44d
Remove RunCommand wrapper and use direct invocation
jeffhandley Feb 8, 2026
76bd53a
Pass all values as explicit named parameters to ProcessSdk
jeffhandley Feb 8, 2026
ddfcdc7
Fix inconsistent casing of \ to \
jeffhandley Feb 8, 2026
c23e220
Remove stale comment and extra blank line
jeffhandley Feb 8, 2026
6e3fb8f
Fix GetReleaseKindFolderName missing dot in GA patch path
jeffhandley Feb 8, 2026
3e74ddf
Convert bool parameters to switch parameters
jeffhandley Feb 8, 2026
21cf78c
Simplify DownloadPackage by making search params optional
jeffhandley Feb 8, 2026
d15caa3
Fix Write-Color to use Write-Host instead of Write-Output
jeffhandley Feb 8, 2026
4a7601c
Use Write-Color consistently instead of Write-Host
jeffhandley Feb 8, 2026
ad3e0ef
Fix MajorMinor ValidatePattern to properly anchor
jeffhandley Feb 8, 2026
cd5a137
Simplify redundant guard in DownloadPackage search term
jeffhandley Feb 8, 2026
deee7ef
Reuse auth headers in DownloadPackage
jeffhandley Feb 8, 2026
e15e904
Use flat2 base URL from service index for downloads
jeffhandley Feb 8, 2026
78c8f34
Pass previewFolderPath as explicit parameter to ProcessSdk
jeffhandley Feb 8, 2026
28ed338
Use named parameters for RunApiDiff call in ProcessSdk
jeffhandley Feb 8, 2026
cfeb131
Replace repetitive ProcessSdk calls with a loop
jeffhandley Feb 8, 2026
5210998
Make CreateReadme only list SDKs that were actually processed
jeffhandley Feb 8, 2026
3df7ce1
Resolve exclude file paths relative to script directory
jeffhandley Feb 8, 2026
04aec1c
Final cleanup: deduplicate scriptDir, pass TmpFolder explicitly, fix …
jeffhandley Feb 8, 2026
c72e80d
Final docs cleanup
jeffhandley Feb 8, 2026
a87eb7f
Default CurrentNuGetFeed to dnceng transport feed based on major version
jeffhandley Feb 10, 2026
585eb0f
Infer current/previous versions from existing api-diff folders
jeffhandley Feb 10, 2026
068cb25
Add Copilot skill for API diff generation
jeffhandley Feb 10, 2026
51da438
Apply review feedback. Remove support for azdo feeds requiring auth.
jeffhandley Feb 10, 2026
b1ac061
Apply suggestions from code review
jeffhandley Feb 13, 2026
d637dcf
Simplify api-diff skill to focus on intent mapping and script execution
jeffhandley Feb 13, 2026
957732c
Default PreviousNuGetFeed to version-appropriate dnceng feed
jeffhandley Feb 13, 2026
070634b
Support per-framework version discovery for pre-.NET 10 versions
jeffhandley Feb 14, 2026
2dfb6b9
Discover next version by probing feed instead of hardcoded progression
jeffhandley Feb 14, 2026
4c895cf
Simplify api-diff skill to single SKILL.md
jeffhandley Feb 14, 2026
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
35 changes: 35 additions & 0 deletions .github/skills/api-diff/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
name: api-diff
description: Generate an API comparison report between two .NET versions using the RunApiDiff.ps1 script. Invoke when the user asks to run, create, or generate an API diff.
disable-model-invocation: true
---

# API Diff Generation

This skill runs `release-notes/RunApiDiff.ps1` to generate API comparison reports between .NET versions.

## Workflow

### 1. Interpret the user's request

Map user input to script parameters. Read [reference/interpreting-input.md](reference/interpreting-input.md) for version format rules, clarification prompts, and examples.

Key points:
- "generate the next API diff" → no params (auto-infers from existing api-diffs)
- "Preview N" → `-PrereleaseLabel preview.N`; "RC N" → `-PrereleaseLabel rc.N`; "GA" → omit PrereleaseLabel
- Full NuGet version strings → use `-PreviousVersion` / `-CurrentVersion` directly

### 2. Construct the command

Build the PowerShell command from the mapped parameters. See [reference/parameters.md](reference/parameters.md) for the full parameter reference.

```powershell
.\release-notes\RunApiDiff.ps1 [mapped parameters]
```

### 3. Run the script

1. Confirm the constructed command with the user before running.
2. Run via PowerShell 7+ (`pwsh`). Set an initial wait of at least 300 seconds.
3. While the script is running, check the output folder for newly created files and mention them to the user as progress updates. Read [reference/progress-monitoring.md](reference/progress-monitoring.md) for disk monitoring instructions.
4. After completion, summarize the results: how many diff files were generated and where.
59 changes: 59 additions & 0 deletions .github/skills/api-diff/reference/interpreting-input.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Interpreting User Input

Users may describe versions in many formats. Map them to script parameters as follows:

| User says | Previous params | Current params |
|---|---|---|
| ".NET 10 GA vs .NET 11 Preview 1" | `-PreviousMajorMinor 10.0` | `-CurrentMajorMinor 11.0 -CurrentPrereleaseLabel preview.1` |
| "net9.0-preview6 to net10.0-preview5" | `-PreviousMajorMinor 9.0 -PreviousPrereleaseLabel preview.6` | `-CurrentMajorMinor 10.0 -CurrentPrereleaseLabel preview.5` |
| ".NET 10 RC 2 vs .NET 10 GA" | `-PreviousMajorMinor 10.0 -PreviousPrereleaseLabel rc.2` | `-CurrentMajorMinor 10.0` |
| "10.0.0-preview.7.25380.108 to 10.0.0-rc.1.25451.107" | `-PreviousVersion "10.0.0-preview.7.25380.108"` | `-CurrentVersion "10.0.0-rc.1.25451.107"` |
| "generate the next API diff" | *(no params — script auto-infers from existing api-diffs)* | |

## Version format rules

- "GA" or no qualifier means a stable release — omit the PrereleaseLabel parameter.
- "Preview N" or "previewN" → `-PrereleaseLabel preview.N` (note the dot separator).
- "RC N" or "rcN" → `-PrereleaseLabel rc.N` (note the dot separator).
- "netX.Y-previewN" (TFM format) → `-MajorMinor X.Y -PrereleaseLabel preview.N`.
- Full NuGet version strings like "10.0.0-preview.7.25380.108" → use `-PreviousVersion` or `-CurrentVersion` directly.
- The "previous" version is always the older/before version and the "current" version is always the newer/after version, regardless of the order the user mentions them.

## Asking for Clarification

If the user's request is ambiguous, ask them interactively:

1. **No versions mentioned**: Ask "How would you like to specify the versions?" with choices:
- "Auto-infer the next version from existing api-diffs (recommended)"
- "I'll provide the current version (e.g., 11.0 Preview 1)"
- "I'll provide both previous and current versions"

2. **Only one version mentioned**: Ask which role it plays — "Is [version] the previous (before) or current (after) version?"

3. **Ambiguous version format**: Ask "What version did you mean?" and offer interpretations. For example, if the user says ".NET 10 Preview", ask which preview number.

## Examples

**User**: "Run an API diff for the next release"
**Action**: Run with no parameters (auto-infers from existing api-diffs):
```powershell
.\release-notes\RunApiDiff.ps1
```

**User**: "Generate an API diff between .NET 10 GA and .NET 11 Preview 1"
**Action**:
```powershell
.\release-notes\RunApiDiff.ps1 -PreviousMajorMinor 10.0 -CurrentMajorMinor 11.0 -CurrentPrereleaseLabel preview.1
```

**User**: "Create an API diff between net8.0-preview6 and net10.0-preview5"
**Action**:
```powershell
.\release-notes\RunApiDiff.ps1 -PreviousMajorMinor 8.0 -PreviousPrereleaseLabel preview.6 -CurrentMajorMinor 10.0 -CurrentPrereleaseLabel preview.5
```

**User**: "Diff 10.0.0-preview.7.25380.108 against 10.0.0-rc.1.25451.107"
**Action**:
```powershell
.\release-notes\RunApiDiff.ps1 -PreviousVersion "10.0.0-preview.7.25380.108" -CurrentVersion "10.0.0-rc.1.25451.107"
```
32 changes: 32 additions & 0 deletions .github/skills/api-diff/reference/parameters.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Script Parameters

Build the PowerShell command from the mapped parameters. Always run from the repository root.

```powershell
.\release-notes\RunApiDiff.ps1 [mapped parameters]
```

## Version parameters

All optional — auto-inferred from existing api-diffs if omitted.

- `-PreviousMajorMinor` — e.g., `10.0`
- `-PreviousPrereleaseLabel` — e.g., `preview.7`, `rc.1` (omit for GA)
- `-CurrentMajorMinor` — e.g., `11.0`
- `-CurrentPrereleaseLabel` — e.g., `preview.1`, `rc.2` (omit for GA)
- `-PreviousVersion` — exact NuGet version string (alternative to MajorMinor+PrereleaseLabel)
- `-CurrentVersion` — exact NuGet version string (alternative to MajorMinor+PrereleaseLabel)

## Feed parameters

Usually not needed.

- `-CurrentNuGetFeed` — defaults to `https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet{MAJOR}/nuget/v3/index.json`
- `-PreviousNuGetFeed` — defaults to `https://api.nuget.org/v3/index.json`

## Switches

- `-ExcludeNetCore` — skip the Microsoft.NETCore.App comparison
- `-ExcludeAspNetCore` — skip the Microsoft.AspNetCore.App comparison
- `-ExcludeWindowsDesktop` — skip the Microsoft.WindowsDesktop.App comparison
- `-InstallApiDiff` — install or update the ApiDiff tool before running
32 changes: 32 additions & 0 deletions .github/skills/api-diff/reference/progress-monitoring.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Progress Monitoring

While the script runs, it writes diff files into the output folder. On each polling iteration (alongside `read_powershell`), list new files on disk and mention them to the user as progress updates.

## Determining the output folder

The output path follows the pattern:

```
release-notes/{MajorMinor}/preview/{milestoneFolder}/api-diff/
```

For example, comparing Preview 1 → Preview 2 of .NET 11.0 writes to `release-notes/11.0/preview/preview2/api-diff/`.

You can determine the path from the script's "Creating new diff folder:" message in the output, or construct it from the version parameters.

## How to check for new files

On each poll, run a `Get-ChildItem` on the output folder (recursively, files only) alongside your `read_powershell` call. Compare the file list to what you saw on the previous poll to identify newly created files.

```powershell
Get-ChildItem -Path "release-notes/{version}/preview/{milestone}/api-diff" -Recurse -File -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Name
```

## What to report

Mention newly appeared files as brief status updates. Group them by SDK subfolder when possible. For example:

> _Microsoft.NETCore.App: 15 diff files generated (System.Runtime.md, System.Collections.md, ...)_
> _Microsoft.AspNetCore.App: 8 diff files generated_

Check for new files each time you call `read_powershell` — make the two calls in parallel. Do not add extra polling rounds just for file checking.
92 changes: 76 additions & 16 deletions release-notes/RunApiDiff.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,87 @@
# RunApiDiff Script

The [`RunApiDiff.ps1`](./RunApiDiff.ps1) script can automatically generate an API comparison report for two specified .NET previews, in the format expected for publishing in the dotnet/core repo.
The [`RunApiDiff.ps1`](./RunApiDiff.ps1) script automatically generates an API comparison report between two .NET versions, in the format expected for publishing in the dotnet/core repo.

## Instructions
## Prerequisites

- PowerShell 7.0 or later
- The [Microsoft.DotNet.ApiDiff.Tool](https://www.nuget.org/packages/Microsoft.DotNet.ApiDiff.Tool). Install from the transport feed matching the version you're comparing, or use `-InstallApiDiff $true` to have the script install it automatically:

1. Clone the dotnet/core repo. Let's assume you clone it into `D:\core`.
2. Create a temporary directory. Let's assume you create it in `D:\tmp`.
3. Install or update your copy of the APIDiff tool (use the latest transport feed):
```
dotnet tool install --global Microsoft.DotNet.ApiDiff.Tool --source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet10-transport/nuget/v3/index.json --prerelease
dotnet tool install --global Microsoft.DotNet.ApiDiff.Tool --prerelease
```
4. Run the command. Execution example:

## Quick Start

When run with no arguments, the script infers the next version to diff by scanning existing `api-diff` folders in the repository. For example, if the latest api-diff is for .NET 10 GA, it will automatically generate a diff for .NET 11 Preview 1.

```powershell
.\RunApiDiff.ps1
```

## Parameters

### Version Parameters

All version parameters can be auto-discovered. When no version information is provided, the script scans existing `api-diff` folders in the repository to find the latest version and infers the next one in the progression (preview.1 → preview.2 → ... → preview.7 → rc.1 → rc.2 → GA → next major preview.1). When `PreviousVersion` or `CurrentVersion` is provided, the `MajorMinor` and `PrereleaseLabel` values are extracted from it automatically.

| Parameter | Description | Default |
|---|---|---|
| `PreviousVersion` | Exact package version for the "before" comparison (e.g., `10.0.0-preview.7.25380.108`). MajorMinor and PrereleaseLabel are extracted automatically. | *(empty — inferred or searched)* |
| `CurrentVersion` | Exact package version for the "after" comparison (e.g., `10.0.0-rc.1.25451.107`). MajorMinor and PrereleaseLabel are extracted automatically. | *(empty — inferred or searched)* |
| `PreviousMajorMinor` | The "before" .NET major.minor version (e.g., `10.0`) | Inferred from api-diffs, extracted from `PreviousVersion`, or discovered from `PreviousNuGetFeed` |
| `PreviousPrereleaseLabel` | Prerelease label for the "before" version (e.g., `preview.7`, `rc.1`). Omit for GA. | Inferred from api-diffs, extracted from `PreviousVersion`, or discovered from `PreviousNuGetFeed` |
| `CurrentMajorMinor` | The "after" .NET major.minor version (e.g., `10.0`) | Inferred from api-diffs, extracted from `CurrentVersion`, or discovered from `CurrentNuGetFeed` |
| `CurrentPrereleaseLabel` | Prerelease label for the "after" version (e.g., `preview.7`, `rc.1`). Omit for GA. | Inferred from api-diffs, extracted from `CurrentVersion`, or discovered from `CurrentNuGetFeed` |

### Feed Parameters

| Parameter | Description | Default |
|---|---|---|
| `CurrentNuGetFeed` | NuGet feed URL for downloading "after" packages | Constructed from `CurrentMajorMinor`: `https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet{MAJOR}/nuget/v3/index.json` |
| `PreviousNuGetFeed` | NuGet feed URL for downloading "before" packages | `https://api.nuget.org/v3/index.json` |

### Path Parameters

| Parameter | Description | Default |
|---|---|---|
| `CoreRepo` | Path to your local clone of the dotnet/core repo | Git repo root relative to the script |
| `TmpFolder` | Working directory for downloaded and extracted packages | Auto-created temp directory |
| `AttributesToExcludeFilePath` | Path to attributes exclusion file | `ApiDiffAttributesToExclude.txt` (same folder as script) |
| `AssembliesToExcludeFilePath` | Path to assemblies exclusion file | `ApiDiffAssembliesToExclude.txt` (same folder as script) |

### Switches

| Parameter | Description |
|---|---|
| `ExcludeNetCore` | Skip the Microsoft.NETCore.App comparison |
| `ExcludeAspNetCore` | Skip the Microsoft.AspNetCore.App comparison |
| `ExcludeWindowsDesktop` | Skip the Microsoft.WindowsDesktop.App comparison |
| `InstallApiDiff` | Install or update the ApiDiff tool before running |

## Examples

```powershell
# Infer the previous version from the most recent existing api-diff
# and infer the the current version to be the next version after it
.\RunApiDiff.ps1

# Specify only the current version; previous is inferred from existing api-diffs
.\RunApiDiff.ps1 -CurrentMajorMinor 11.0 -CurrentPrereleaseLabel preview.2

# Specify both versions explicitly
.\RunApiDiff.ps1 `
-PreviousMajorMinor 10.0 -PreviousPrereleaseLabel preview.7 `
-CurrentMajorMinor 10.0 -CurrentPrereleaseLabel rc.1

# Use exact NuGet package versions (MajorMinor and PrereleaseLabel are extracted automatically)
.\RunApiDiff.ps1 `
-PreviousVersion "10.0.0-preview.7.25380.108" `
-CurrentVersion "10.0.0-rc.1.25451.107"

# Use a custom feed for the current version's packages
.\RunApiDiff.ps1 `
-PreviousDotNetVersion 10.0 `
-PreviousPreviewOrRC preview `
-PreviousPreviewNumberVersion 1 `
-CurrentDotNetVersion 10.0 `
-CurrentPreviewOrRC preview `
-CurrentPreviewNumberVersion 2 `
-CoreRepo D:\core\ `
-TmpFolder D:\tmp\
-CurrentNuGetFeed "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet11/nuget/v3/index.json"
```

Example of what this script generates: [API diff between .NET 10.0 Preview1 and .NET 10 Preview2](https://github.com/dotnet/core/pull/9771)
Example of what this script generates: [API diff between .NET 10 GA and .NET 11 Preview 1 (dotnet/core#10240)](https://github.com/dotnet/core/pull/10240/changes)
Loading