Skip to content

RunApiDiff script and documentation improvements#10241

Open
jeffhandley wants to merge 49 commits intomainfrom
jeffhandley/apidiff-improvements
Open

RunApiDiff script and documentation improvements#10241
jeffhandley wants to merge 49 commits intomainfrom
jeffhandley/apidiff-improvements

Conversation

@jeffhandley
Copy link
Member

Running the API Diff for 11.0.0-preview.1 revealed some opportunities to make this script more user-friendly. The first hurdle faced was the search index for the staging NuGet feed for preview.1 did not have any results, and this led to needing to find all of the version parameter values through other means. Copilot CLI figured it all out, but it was difficult to achieve by hand, and its results weren't fully deterministic. Once the logic was understood, this led to a series of Copilot-authored improvements to the script and documentation with each step captured as its own commit.

A lot of the documentation and logic was based on running the diff after a release was published, but we began running it before the releases during .NET 10 and we intend to continue that approach going forward.

The SearchQueryService on some Azure DevOps feeds (especially per-build
shipping feeds) has an unpopulated search index that returns 0 results.
The flat2 (PackageBaseAddress) API works reliably on all feeds.

This changes DownloadPackage to try flat2 first, falling back to
SearchQueryService if flat2 doesn't find a match.
Make the -CoreRepo parameter optional. When omitted, the script resolves
the git repository root relative to its own location using
'git rev-parse --show-toplevel'. If the root cannot be determined, it
fails with a descriptive error.
Paths containing ~ or relative segments fail when passed to the api diff
tool. Resolve both paths to their full absolute form before use.
The previous/before version is typically a GA release available on
nuget.org. Default to the public NuGet feed instead of the dotnet10
Azure DevOps feed.
…nal for GA

Rename PreviousPreviewOrRC/CurrentPreviewOrRC to PreviousReleaseKind/
CurrentReleaseKind for clarity.

Make PreviousPreviewNumberVersion and CurrentPreviewNumberVersion
optional, defaulting to '0' when the release kind is 'ga'. For non-GA
release kinds, a validation error is raised if the version number is
not provided.
…wRCNumber

Rename PreviousDotNetVersion/CurrentDotNetVersion to PreviousMajorMinor/
CurrentMajorMinor and PreviousPreviewNumberVersion/
CurrentPreviewNumberVersion to PreviousPreviewRCNumber/
CurrentPreviewRCNumber for clarity.
When TmpFolder is not specified, create a unique temporary directory
using GetTempPath and GetRandomFileName.
When CurrentMajorMinor, CurrentReleaseKind, or CurrentPreviewRCNumber
are not specified, query the CurrentNuGetFeed for the latest
Microsoft.NETCore.App.Ref package version and parse the version
components from it (e.g. 11.0.0-preview.1.26104.118 -> 11.0, preview, 1).
Extract version discovery into a reusable DiscoverVersionFromFeed
function and apply it to both Previous and Current parameters. When
PreviousMajorMinor or PreviousReleaseKind are not specified, they are
discovered from the PreviousNuGetFeed (default: nuget.org, which will
resolve to the latest GA version).
Allow the simplest invocation:
  .\RunApiDiff.ps1 <current-nuget-feed-url>
Document all parameters, their defaults, and auto-discovery behavior.
Add quick start, prerequisites, and multiple usage examples.
Note the transport feed should match the version being compared, and
mention the -InstallApiDiff flag as an alternative.
Both feeds now default to nuget.org. The same-version validation
added previously will catch the case where both resolve to the same
version and prompt the user to specify different feeds or explicit
version parameters.
Replace the separate -PreviousReleaseKind/-PreviousPreviewRCNumber and
-CurrentReleaseKind/-CurrentPreviewRCNumber parameters with single
-PreviousPrereleaseLabel and -CurrentPrereleaseLabel parameters that
accept values like 'preview.7' or 'rc.1'. Omit for GA releases.

The labels are parsed internally into ReleaseKind and PreviewRCNumber
for use by the existing helper functions.
…el from it

Rename -PreviousPackageVersion/-CurrentPackageVersion to
-PreviousVersion/-CurrentVersion. When a Version is provided, the
MajorMinor and PrereleaseLabel values are automatically parsed from
it, eliminating the need to specify them separately.

Add ValidatePattern to PrereleaseLabel parameters to enforce the
'preview.N' or 'rc.N' format.

Update examples to show the simplified usage with only -PreviousVersion
and -CurrentVersion.
Move ParseVersionString to the Functions section and reuse it inside
DiscoverVersionFromFeed instead of duplicating the regex parsing.
All helper functions are now defined together in the Functions section
rather than being scattered in the execution section.
This function was never called and referenced a nonexistent variable
(\). It was leftover from when the apidiff tool was built from
source rather than installed as a dotnet tool.
Replace Invoke-Expression string-building with direct & invocation and
argument splatting for the apidiff tool call. This avoids the fragile
Invoke-Expression pattern and properly handles paths with spaces.
Add previousMajorMinor, previousReleaseKind, previousPreviewRCNumber,
currentMajorMinor, currentReleaseKind, and currentPreviewRCNumber as
explicit parameters instead of referencing script-scoped variables.
Switch callers to use named parameters for clarity. Mark required
parameters as Mandatory.
Remove the misleading 'Generate strings with no whitespace' comment
that no longer described what followed, and remove a double blank line.
The GA patch branch was producing folder names like '7.01' instead of
'7.0.1' due to a missing dot separator between dotNetVersion and
previewNumberVersion.
Change ExcludeNetCore, ExcludeAspNetCore, ExcludeWindowsDesktop, and
InstallApiDiff from [bool] to [switch]. This follows PowerShell idiom,
allowing -ExcludeNetCore instead of -ExcludeNetCore \$true.
Make releaseKind and previewNumberVersion optional in DownloadPackage
since they are unused when an exact version is provided. Add validation
that either version or both search params are specified. Switch all
DownloadPackage calls to use named parameters for clarity.
Write-Output sends to stdout which can interfere with function return
values. Write-Host sends to the display stream only, which is correct
for informational/colored messages.
The pattern was unanchored and too permissive, matching partial strings
like '7.0abc'. Now uses ^(\d+\.\d+)?$ to match either empty or a
properly formatted major.minor version.
The validation above already ensures both releaseKind and
previewNumberVersion are non-empty, so the ElseIf guard was
always true. Replace with a simple Else.
Call GetAuthHeadersForFeed once at the top of DownloadPackage and reuse
the headers for both version search and package download, instead of
calling it twice.
Instead of string-replacing the feed URL to construct a download path,
use the PackageBaseAddress endpoint discovered from the service index.
This handles feeds with non-standard URL patterns correctly.
Eliminates the last script-scoped variable reference from ProcessSdk.
Replaces 11 positional arguments with named parameters for clarity
and to prevent parameter ordering mistakes.
Build an array of SDK names filtered by exclude flags, then loop over
them with splatted common parameters. Eliminates three nearly identical
long lines.
Pass the array of SDK names to CreateReadme so it only generates links
for SDKs that were diffed, avoiding broken links when Exclude flags
are used.
The default exclude file paths (ApiDiffAttributesToExclude.txt and
ApiDiffAssembliesToExclude.txt) were resolving relative to the current
working directory instead of the script's directory, causing
FileNotFoundException when running from the repo root.
…stale comments

- Set \ once before CoreRepo and exclude file resolution
  instead of computing it twice.
- Add tmpFolder as an explicit parameter to DownloadPackage and
  ProcessSdk, eliminating the last script-scoped variable reference
  from helper functions.
- Remove stale '#D:\\core' comment from CoreRepo parameter.
- Fix misleading 'Recreate api-diff folder' comment to 'Create if
  it doesn't exist'.
@jeffhandley jeffhandley requested review from ericstj and jozkee February 8, 2026 11:42
@jeffhandley jeffhandley self-assigned this Feb 8, 2026
Introduce a project-scoped Copilot skill (.github/skills/api-diff/) that
guides API diff generation using release-notes/RunApiDiff.ps1.

SKILL.md provides a concise workflow overview with links to reference
files for each stage:

- reference/interpreting-input.md: version format mapping rules,
  clarification prompts for ambiguous input, and usage examples
- reference/parameters.md: full script parameter reference (version,
  feed, and switch parameters)
- reference/progress-monitoring.md: disk-based progress monitoring
  to report newly generated diff files during script execution
@jeffhandley jeffhandley requested a review from ericstj February 10, 2026 13:48
jeffhandley and others added 6 commits February 13, 2026 09:20
Co-authored-by: Eric StJohn <ericstj@microsoft.com>
Reduce the skill's responsibility to a single job: interpret the user's
prompt, map it to RunApiDiff.ps1 parameters, and run the script. Remove
interactive clarification flows, progress monitoring via disk polling,
and duplicated parameter logic that was redundant with RunApiDiff.md/ps1.

Add note about ANSI progress bar output making completion detection
difficult, instructing agents to check process exit status instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Change PreviousNuGetFeed default from nuget.org to the dnceng public
transport feed constructed from PreviousMajorMinor, matching the
existing CurrentNuGetFeed behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
DiscoverVersionFromFeed now accepts an sdkName parameter instead of
hardcoding microsoft.netcore.app.ref, enabling version queries for
AspNetCore and WindowsDesktop framework packs independently.

ProcessSdk no longer passes exact NETCore versions to non-NETCore SDK
downloads, allowing each framework to resolve its own version from
the feed. This handles pre-.NET 10 releases where framework versions
could differ.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace GetNextVersion (which hardcoded preview.7 → rc.1, rc.2 → ga)
with GetNextVersionFromFeed that queries the NuGet feed to find the
actual next milestone. This handles any number of previews or RCs
without assumptions about the release cadence.

When no newer version exists on the same major, the function probes
the next major version's feed automatically.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove reference/interpreting-input.md and reference/parameters.md,
consolidating the skill into a single file. The skill now only adds
natural language to parameter mapping and defers to RunApiDiff.md for
the full parameter reference.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants