1
0
mirror of synced 2025-12-19 09:50:46 -05:00
Files
core/release-notes/RunApiDiff.ps1
David Cantú 0e13314745 ApiDiff.ps: allow exact versions, allow arbitrary feeds, and use az cli for auth if needed (#10139)
* Add exact version lookup for ApiDiff.ps1

* Allow passing arbitrary NuGet feeds

* Use az cli for auth if needed

* Split NuGetFeed into two for previous and current

* Support auth also on version search path

* Address feedback ExactVersion -> Version
2025-11-04 14:12:45 -08:00

830 lines
28 KiB
PowerShell

# This script allows running API-diff to generate the dotnet/core report that compares the APIs introduced between two previews, in the format expected for publishing in the dotnet/core repo.
# Prerequisites:
# - PowerShell 7.0 or later
# - Azure CLI (az) installed and logged in (required for authenticated Azure DevOps feeds): Run 'az login' before using private feeds
# Usage:
# RunApiDiff.ps1
# -PreviousDotNetVersion : The 'before' .NET version: '6.0', '7.0', '8.0', etc.
# -PreviousPreviewOrRC : An optional word that indicates if the 'before' version is a Preview, an RC, or GA. Accepted values: "preview", "rc" or "ga".
# -PreviousPreviewNumberVersion : The optional preview or RC number of the 'before' version: '1', '2', '3', etc. For GA, this number is the 3rd one in the released version (7.0.0, 7.0.1, 7.0.2, ...).
# -CurrentDotNetVersion : The 'after' .NET version: '6.0', '7.0', '8.0', etc.
# -CurrentPreviewOrRC : An optional word that indicates if the 'after' version is a Preview, an RC, or GA. Accepted values: "preview", "rc" or "ga".
# -CurrentPreviewNumberVersion : The optional preview or RC number of the 'before' version: '1', '2', '3', etc. For GA, this number is the 3rd one in the released version (7.0.0, 7.0.1, 7.0.2, ...).
# -CoreRepo : The full path to your local clone of the dotnet/core repo.
# -TmpFolder : The full path to the folder where the assets will be downloaded, extracted and compared.
# -AttributesToExcludeFilePath : The full path to the file containing the attributes to exclude from the report. By default, it is "ApiDiffAttributesToExclude.txt" in the same folder as this script.
# -AssembliesToExcludeFilePath : The full path to the file containing the assemblies to exclude from the report. By default, it is "ApiDiffAssembliesToExclude.txt" in the same folder as this script.
# -PreviousNuGetFeed : The NuGet feed URL to use for downloading previous/before packages. By default, uses https://dnceng.pkgs.visualstudio.com/public/_packaging/dotnet10/nuget/v3/index.json
# -CurrentNuGetFeed : The NuGet feed URL to use for downloading current/after packages. By default, uses https://dnceng.pkgs.visualstudio.com/public/_packaging/dotnet10/nuget/v3/index.json
# -ExcludeNetCore : Optional boolean to exclude the NETCore comparison. Default is false.
# -ExcludeAspNetCore : Optional boolean to exclude the AspNetCore comparison. Default is false.
# -ExcludeWindowsDesktop : Optional boolean to exclude the WindowsDesktop comparison. Default is false.
# -InstallApiDiff : Optional boolean to install or update the ApiDiff tool. Default is false.
# -PreviousPackageVersion : Optional exact package version for the previous/before comparison (e.g., "10.0.0-rc.1.25451.107"). Overrides version search logic.
# -CurrentPackageVersion : Optional exact package version for the current/after comparison (e.g., "10.0.0-rc.2.25502.107"). Overrides version search logic.
# Example:
# .\RunApiDiff.ps1 -PreviousDotNetVersion 9.0 -PreviousPreviewOrRC preview -PreviousPreviewNumberVersion 7 -CurrentDotNetVersion 9.0 -CurrentPreviewOrRC rc -CurrentPreviewNumberVersion 1 -CoreRepo C:\Users\calope\source\repos\core\ -SdkRepo C:\Users\calope\source\repos\sdk\ -TmpFolder C:\Users\calope\source\repos\tmp\
# Example with exact package versions:
# .\RunApiDiff.ps1 -PreviousDotNetVersion 10.0 -PreviousPreviewOrRC RC -PreviousPreviewNumberVersion 1 -CurrentDotNetVersion 10.0 -CurrentPreviewOrRC RC -CurrentPreviewNumberVersion 2 -CoreRepo D:\core\ -TmpFolder D:\tmp -PreviousPackageVersion "10.0.0-rc.1.25451.107" -CurrentPackageVersion "10.0.0-rc.2.25502.107"
# Example with custom NuGet feed:
# .\RunApiDiff.ps1 -PreviousDotNetVersion 9.0 -PreviousPreviewOrRC preview -PreviousPreviewNumberVersion 7 -CurrentDotNetVersion 9.0 -CurrentPreviewOrRC rc -CurrentPreviewNumberVersion 1 -CoreRepo D:\core\ -TmpFolder D:\tmp -PreviousNuGetFeed "https://api.nuget.org/v3/index.json" -CurrentNuGetFeed "https://api.nuget.org/v3/index.json"
Param (
[Parameter(Mandatory = $true)]
[ValidatePattern("\d+\.\d")]
[string]
$PreviousDotNetVersion # 7.0, 8.0, 9.0, ...
,
[Parameter(Mandatory = $true)]
[string]
[ValidateSet("preview", "rc", "ga")]
$PreviousPreviewOrRC
,
[Parameter(Mandatory = $true)]
[ValidatePattern("(\d+)?")]
[string]
$PreviousPreviewNumberVersion # 0, 1, 2, 3, ...
,
[Parameter(Mandatory = $true)]
[ValidatePattern("\d+\.\d")]
[string]
$CurrentDotNetVersion # 7.0, 8.0, 9.0, ...
,
[Parameter(Mandatory = $true)]
[string]
[ValidateSet("preview", "rc", "ga")]
$CurrentPreviewOrRC
,
[Parameter(Mandatory = $true)]
[ValidatePattern("(\d+)?")]
[string]
$CurrentPreviewNumberVersion # 0, 1, 2, 3, ...
,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$CoreRepo #"D:\\core"
,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$TmpFolder #"D:\tmp"
,
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]
$AttributesToExcludeFilePath = "ApiDiffAttributesToExclude.txt"
,
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]
$AssembliesToExcludeFilePath = "ApiDiffAssembliesToExclude.txt"
,
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]
$PreviousNuGetFeed = "https://dnceng.pkgs.visualstudio.com/public/_packaging/dotnet10/nuget/v3/index.json"
,
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]
$CurrentNuGetFeed = "https://dnceng.pkgs.visualstudio.com/public/_packaging/dotnet10/nuget/v3/index.json"
,
[Parameter(Mandatory = $false)]
[bool]
$ExcludeNetCore = $false
,
[Parameter(Mandatory = $false)]
[bool]
$ExcludeAspNetCore = $false
,
[Parameter(Mandatory = $false)]
[bool]
$ExcludeWindowsDesktop = $false
,
[Parameter(Mandatory = $false)]
[bool]
$InstallApiDiff = $false
,
[Parameter(Mandatory = $false)]
[string]
$PreviousPackageVersion = ""
,
[Parameter(Mandatory = $false)]
[string]
$CurrentPackageVersion = ""
)
#######################
### Start Functions ###
#######################
Function Write-Color {
Param (
[ValidateNotNullOrEmpty()]
[string] $newColor
)
$oldColor = $host.UI.RawUI.ForegroundColor
$host.UI.RawUI.ForegroundColor = $newColor
If ($args) {
Write-Output $args
}
Else {
$input | Write-Output
}
$host.UI.RawUI.ForegroundColor = $oldColor
}
Function VerifyPathOrExit {
Param (
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$path
)
If (-Not (Test-Path -Path $path)) {
Write-Error "The path '$path' does not exist." -ErrorAction Stop
}
}
Function RemoveFolderIfExists {
Param (
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$path
)
If (Test-Path -Path $path) {
Write-Color yellow "Removing existing folder: $path"
Remove-Item -Recurse -Path $path
}
}
Function RecreateFolder {
Param (
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$path
)
RemoveFolderIfExists $path
Write-Color cyan "Creating new folder: $path"
New-Item -ItemType Directory -Path $path
}
Function VerifyCountDlls {
Param (
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$path
)
VerifyPathOrExit $path
$count = (Get-ChildItem -Path $path -Filter "*.dll" | Measure-Object).Count
If ($count -eq 0) {
Write-Error "There are no DLL files inside the folder." -ErrorAction Stop
}
}
Function RunCommand {
Param (
[Parameter(Mandatory = $True)]
[ValidateNotNullOrEmpty()]
[string]
$command
)
Write-Color yellow $command
Invoke-Expression "$command"
}
Function GetDotNetFullName {
Param (
[Parameter(Mandatory = $true)]
[bool]
$IsComparingReleases
,
[Parameter(Mandatory = $true)]
[ValidatePattern("\d+\.\d")]
[string]
$dotNetVersion # 7.0, 8.0, 9.0, ...
,
[Parameter(Mandatory = $true)]
[string]
[ValidateSet("preview", "rc", "ga")]
$previewOrRC
,
[Parameter(Mandatory = $true)]
[ValidatePattern("(\d+)?")]
[string]
$previewNumberVersion # 0, 1, 2, 3, ...
)
If ($IsComparingReleases) {
Return "$dotNetVersion.$previewNumberVersion"
}
If ($previewOrRC -eq "ga") {
If ($previewNumberVersion -eq "0") {
# Example: Don't return "7.0-ga0", instead just return "7.0-ga"
Return "$dotNetVersion-$previewOrRC"
}
# Examples: Don't include "ga", instead just return "7.0.1", "7.0.2"
Return "$dotNetVersion.$previewNumberVersion"
}
# Examples: "7.0-preview5", "7.0-rc2", "7.0-ga"
Return "$dotNetVersion-$previewOrRC$previewNumberVersion"
}
Function GetDotNetFriendlyName {
Param (
[Parameter(Mandatory = $true)]
[ValidatePattern("\d+\.\d")]
[string]
$DotNetVersion # 7.0, 8.0, 9.0, ...
,
[Parameter(Mandatory = $true)]
[string]
[ValidateSet("preview", "rc", "ga")]
$PreviewOrRC
,
[Parameter(Mandatory = $true)]
[ValidatePattern("(\d+)?")]
[string]
$PreviewNumberVersion # 0, 1, 2, 3, ...
)
$friendlyPreview = ""
If ($PreviewOrRC -eq "preview") {
$friendlyPreview = "Preview"
}
ElseIf ($PreviewOrRC -eq "rc") {
$friendlyPreview = "RC"
}
ElseIf ($PreviewOrRC -eq "ga") {
$friendlyPreview = "GA"
If ($PreviewNumberVersion -eq 0) {
# Example: Don't return "7.0 GA 0", instead just return "7.0 GA"
Return ".NET $DotNetVersion $friendlyPreview"
}
# Examples: Don't include "ga", instead just return "7.0.1", "7.0.2"
Return ".NET $DotNetVersion.$PreviewNumberVersion"
}
# Examples: "7.0 Preview 5", "7.0 RC 2"
Return ".NET $DotNetVersion $friendlyPreview $PreviewNumberVersion"
}
Function GetPreviewOrRCFolderName {
Param (
[Parameter(Mandatory = $true)]
[ValidatePattern("\d+\.\d")]
[string]
$dotNetVersion # 7.0, 8.0, 9.0, ...
,
[Parameter(Mandatory = $true)]
[string]
[ValidateSet("preview", "rc", "ga")]
$previewOrRC
,
[Parameter(Mandatory = $true)]
[ValidatePattern("(\d+)?")]
[string]
$previewNumberVersion # 0, 1, 2, 3, ...
)
If ($previewOrRC -eq "ga") {
If ($previewNumberVersion -eq "0") {
# return "ga", not "ga0"
Return $previewOrRC
}
# return "7.0.1", "7.0.2", not "ga1, ga2"
Return "$dotNetVersion$previewNumberVersion"
}
Return "$previewOrRC$previewNumberVersion"
}
Function GetPreviewFolderPath {
Param (
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$rootFolder #"D:\\core"
,
[Parameter(Mandatory = $true)]
[ValidatePattern("\d+\.\d")]
[string]
$dotNetVersion # 7.0, 8.0, 9.0, ...
,
[Parameter(Mandatory = $true)]
[string]
[ValidateSet("preview", "rc", "ga")]
$previewOrRC
,
[Parameter(Mandatory = $true)]
[ValidatePattern("(\d+)?")]
[string]
$previewNumberVersion # 0, 1, 2, 3, ...
,
[Parameter(Mandatory = $true)]
[bool]
$IsComparingReleases # True when comparing 8.0 GA with 9.0 GA
)
$prefixFolder = [IO.Path]::Combine($rootFolder, "release-notes", $dotNetVersion)
$apiDiffFolderName = "api-diff"
If ($IsComparingReleases) {
Return [IO.Path]::Combine($prefixFolder, "$dotNetVersion.$previewNumberVersion", $apiDiffFolderName)
}
$previewOrRCFolderName = GetPreviewOrRCFolderName $dotNetVersion $previewOrRC $previewNumberVersion
Return [IO.Path]::Combine($prefixFolder, "preview", $previewOrRCFolderName, $apiDiffFolderName)
}
Function RunApiDiff {
Param (
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$apiDiffExe
,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$outputFolder
,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$beforeFolder
,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$afterFolder
,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$tableOfContentsFileNamePrefix
,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$assembliesToExclude
,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$attributesToExclude
,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$beforeFriendlyName
,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$afterFriendlyName
,
[Parameter(Mandatory = $false)]
[string]
$beforeReferenceFolder = ""
,
[Parameter(Mandatory = $false)]
[string]
$afterReferenceFolder = ""
)
VerifyPathOrExit $apiDiffExe
VerifyPathOrExit $beforeFolder
VerifyPathOrExit $afterFolder
$referenceParams = ""
if (-not [string]::IsNullOrEmpty($beforeReferenceFolder) -and -not [string]::IsNullOrEmpty($afterReferenceFolder)) {
VerifyPathOrExit $beforeReferenceFolder
VerifyPathOrExit $afterReferenceFolder
$referenceParams = " -rb '$beforeReferenceFolder' -ra '$afterReferenceFolder'"
}
RunCommand "$apiDiffExe -b '$beforeFolder' -a '$afterFolder' -o '$outputFolder' -tc '$tableOfContentsFileNamePrefix' -eas '$assembliesToExclude' -eattrs '$attributesToExclude' -bfn '$beforeFriendlyName' -afn '$afterFriendlyName'$referenceParams"
}
Function CreateReadme {
Param (
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$previewFolderPath
,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$dotNetFriendlyName
,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$dotNetFullName
)
$readmePath = [IO.Path]::Combine($previewFolderPath, "README.md")
If (Test-Path -Path $readmePath) {
Remove-Item -Path $readmePath
}
New-Item -ItemType File $readmePath
Add-Content $readmePath "# $dotNetFriendlyName API Changes"
Add-Content $readmePath ""
Add-Content $readmePath "The following API changes were made in $($dotNetFriendlyName):"
Add-Content $readmePath ""
Add-Content $readmePath "- [Microsoft.NETCore.App](./Microsoft.NETCore.App/$dotNetFullName.md)"
Add-Content $readmePath "- [Microsoft.AspNetCore.App](./Microsoft.AspNetCore.App/$dotNetFullName.md)"
Add-Content $readmePath "- [Microsoft.WindowsDesktop.App](./Microsoft.WindowsDesktop.App/$dotNetFullName.md)"
}
Function GetAuthHeadersForFeed {
Param (
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$feedUrl
)
# Check if authentication is required (internal dnceng feeds)
if ($feedUrl -match "dnceng/internal") {
try {
# Try to get Azure DevOps token using az CLI
$token = az account get-access-token --resource "499b84ac-1321-427f-aa17-267ca6975798" --query accessToken -o tsv 2>$null
if ($token) {
Write-Host "Using Azure CLI authentication for internal Azure DevOps feed" -ForegroundColor Cyan
return @{
Authorization = "Bearer $token"
}
}
else {
Write-Error "Could not get Azure DevOps token from Azure CLI. Please run 'az login' first." -ErrorAction Stop
}
}
catch {
Write-Error "Azure CLI not available or not logged in. Please run 'az login' first." -ErrorAction Stop
}
}
return @{}
}
Function RebuildIfExeNotFound {
Param (
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$exePath
,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$projectPath
,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$artifactsPath
)
VerifyPathOrExit $projectPath
If (-Not (Test-Path -Path $exePath)) {
# Building the project
Write-Color cyan "Building project '$projectPath'"
RunCommand "$SdkRepo/.dotnet/dotnet build -c release $projectPath"
# Verifying expected output from building
VerifyPathOrExit $artifactsPath
VerifyPathOrExit $exePath
}
}
Function DownloadPackage {
Param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$nuGetFeed
,
[Parameter(Mandatory = $true)]
[ValidateSet("NETCore", "AspNetCore", "WindowsDesktop")]
[string]
$sdkName
,
[Parameter(Mandatory = $true)]
[ValidateSet("Before", "After")]
[string]
$beforeOrAfter
,
[Parameter(Mandatory = $true)]
[ValidatePattern("\d+\.\d")]
[string]
$dotNetVersion
,
[Parameter(Mandatory = $true)]
[ValidateSet("preview", "rc", "ga")]
[string]
$previewOrRC
,
[Parameter(Mandatory = $true)]
[ValidatePattern("(\d+)?")]
[string]
$previewNumberVersion
,
[Parameter(Mandatory = $false)]
[string]
$version = ""
,
[ref]
$resultingPath
)
$fullSdkName = "Microsoft.$sdkName.App"
$destinationFolder = [IO.Path]::Combine($TmpFolder, "$fullSdkName.$beforeOrAfter")
RecreateFolder $destinationFolder
$refPackageName = "$fullSdkName.Ref"
# If exact version is provided, use it directly
If (-Not ([System.String]::IsNullOrWhiteSpace($version))) {
Write-Color cyan "Using exact package version: $version"
}
Else {
# Otherwise, search for the package version
$searchTerm = ""
If ($previewOrRC -eq "ga") {
$searchTerm = "$dotNetversion.$previewNumberVersion"
}
ElseIf (-Not ([System.String]::IsNullOrWhiteSpace($previewOrRC)) -And -Not ([System.String]::IsNullOrWhiteSpace($previewNumberVersion))) {
$searchTerm = "$dotNetversion.*-$previewOrRC.$previewNumberVersion*"
}
# Use NuGet API directly instead of Find-Package to support authenticated feeds
Write-Color cyan "Searching for package '$refPackageName' matching '$searchTerm' in feed '$nuGetFeed'..."
$headers = GetAuthHeadersForFeed $nuGetFeed
# Get service index
$serviceIndex = Invoke-RestMethod -Uri $nuGetFeed -Headers $headers
$searchQueryService = $serviceIndex.resources | Where-Object { $_.'@type' -match 'SearchQueryService' } | Select-Object -First 1
if (-not $searchQueryService) {
Write-Error "Could not find SearchQueryService endpoint in feed '$nuGetFeed'" -ErrorAction Stop
}
$searchUrl = $searchQueryService.'@id'
$searchParams = @{
Uri = "$searchUrl`?q=$refPackageName&prerelease=true&take=1"
Headers = $headers
}
$searchResults = Invoke-RestMethod @searchParams
If (-not $searchResults.data -or $searchResults.data.Count -eq 0) {
Write-Error "No NuGet packages found with ref package name '$refPackageName' in feed '$nuGetFeed'" -ErrorAction Stop
}
$package = $searchResults.data | Where-Object { $_.id -eq $refPackageName } | Select-Object -First 1
If (-not $package) {
Write-Error "Package '$refPackageName' not found in search results" -ErrorAction Stop
}
# Filter versions matching search term
$matchingVersions = $package.versions | Where-Object -Property version -Like $searchTerm | Sort-Object version -Descending
If ($matchingVersions.Count -eq 0) {
Write-Error "No NuGet packages found with search term '$searchTerm'." -ErrorAction Stop
}
$version = $matchingVersions[0].version
}
$nupkgFile = [IO.Path]::Combine($TmpFolder, "$refPackageName.$version.nupkg")
If (-Not(Test-Path -Path $nupkgFile)) {
# Construct download URL based on the feed
if ($nuGetFeed -eq "https://api.nuget.org/v3/index.json") {
# Use NuGet.org v2 API for downloads
$nupkgUrl = "https://www.nuget.org/api/v2/package/$refPackageName/$version"
}
else {
# Use flat2 pattern for all other feeds
$baseUrl = $nuGetFeed -replace "/v3/index\.json$", ""
$nupkgUrl = "$baseUrl/v3/flat2/$refPackageName/$version/$refPackageName.$version.nupkg"
}
Write-Color yellow "Downloading '$nupkgUrl' to '$nupkgFile'..."
# Get authentication headers if required
$headers = GetAuthHeadersForFeed $nuGetFeed
if ($headers.Count -gt 0) {
Invoke-WebRequest -Uri $nupkgUrl -OutFile $nupkgFile -Headers $headers
}
else {
Invoke-WebRequest -Uri $nupkgUrl -OutFile $nupkgFile
}
VerifyPathOrExit $nupkgFile
}
Else {
Write-Color green "File '$nupkgFile' already exists locally. Skipping re-download."
}
Expand-Archive -Path $nupkgFile -DestinationPath $destinationFolder -ErrorAction Stop
$dllPath = [IO.Path]::Combine($destinationFolder, "ref", "net$dotNetVersion")
VerifyPathOrExit $dllPath
VerifyCountDlls $dllPath
$resultingPath.value = $dllPath
}
Function ProcessSdk
{
Param(
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]
$sdkName
,
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]
$previousNuGetFeed
,
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]
$currentNuGetFeed
,
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]
$apiDiffExe
,
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]
$currentDotNetFullName
,
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]
$assembliesToExclude
,
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]
$attributesToExclude
,
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]
$previousDotNetFriendlyName
,
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]
$currentDotNetFriendlyName
,
[Parameter(Mandatory = $false)]
[string]
$previousVersion = ""
,
[Parameter(Mandatory = $false)]
[string]
$currentVersion = ""
)
$beforeDllFolder = ""
DownloadPackage $previousNuGetFeed $sdkName "Before" $PreviousDotNetVersion $PreviousPreviewOrRC $PreviousPreviewNumberVersion $previousVersion ([ref]$beforeDllFolder)
VerifyPathOrExit $beforeDllFolder
$afterDllFolder = ""
DownloadPackage $currentNuGetFeed $sdkName "After" $CurrentDotNetVersion $CurrentPreviewOrRC $CurrentPreviewNumberVersion $currentVersion ([ref]$afterDllFolder)
VerifyPathOrExit $afterDllFolder
# For AspNetCore and WindowsDesktop, also download NETCore references to provide core assemblies
$beforeReferenceFolder = ""
$afterReferenceFolder = ""
if ($sdkName -eq "AspNetCore" -or $sdkName -eq "WindowsDesktop") {
DownloadPackage $previousNuGetFeed "NETCore" "Before" $PreviousDotNetVersion $PreviousPreviewOrRC $PreviousPreviewNumberVersion $previousVersion ([ref]$beforeReferenceFolder)
VerifyPathOrExit $beforeReferenceFolder
DownloadPackage $currentNuGetFeed "NETCore" "After" $CurrentDotNetVersion $CurrentPreviewOrRC $CurrentPreviewNumberVersion $currentVersion ([ref]$afterReferenceFolder)
VerifyPathOrExit $afterReferenceFolder
}
$targetFolder = [IO.Path]::Combine($previewFolderPath, "Microsoft.$sdkName.App")
RecreateFolder $targetFolder
RunApiDiff $apiDiffExe $targetFolder $beforeDllFolder $afterDllFolder $currentDotNetFullName $assembliesToExclude $attributesToExclude $previousDotNetFriendlyName $currentDotNetFriendlyName $beforeReferenceFolder $afterReferenceFolder
}
#####################
### End Functions ###
#####################
#######################
### Start Execution ###
#######################
if ($PSVersionTable.PSVersion.Major -lt 7) {
Write-Error "This script requires PowerShell 7.0 or later. See https://aka.ms/PSWindows for instructions." -ErrorAction Stop
}
## Generate strings with no whitespace
# True when comparing 8.0 GA with 9.0 GA
$IsComparingReleases = ($PreviousDotNetVersion -Ne $CurrentDotNetVersion) -And ($PreviousPreviewOrRC -Eq "ga") -And ($CurrentPreviewOrRC -eq "ga")
## Check folders passed as parameters exist
VerifyPathOrExit $CoreRepo
VerifyPathOrExit $TmpFolder
$currentMajorVersion = $CurrentDotNetVersion.Split(".")[0]
$InstallApiDiffCommand = "dotnet tool install --global Microsoft.DotNet.ApiDiff.Tool --source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet$currentMajorVersion-transport/nuget/v3/index.json --prerelease"
if ($InstallApiDiff) {
Write-Color white "Installing ApiDiff tool..."
RunCommand $InstallApiDiffCommand
}
$apiDiffCommand = get-command "apidiff" -ErrorAction SilentlyContinue
if (-Not $apiDiffCommand)
{
Write-Error "The command apidiff could not be found. Please first install the tool using the following command: $InstallApiDiffCommand" -ErrorAction Stop
}
$apiDiffExe = $apiDiffCommand.Source
## Recreate api-diff folder in core repo folder
$previewFolderPath = GetPreviewFolderPath $CoreRepo $CurrentDotNetVersion $CurrentPreviewOrRC $CurrentPreviewNumberVersion $IsComparingReleases
If (-Not (Test-Path -Path $previewFolderPath))
{
Write-Color white "Creating new diff folder: $previewFolderPath"
New-Item -ItemType Directory -Path $previewFolderPath
}
## Run the ApiDiff commands
# Example: "10.0-preview2"
$currentDotNetFullName = GetDotNetFullName $IsComparingReleases $CurrentDotNetVersion $CurrentPreviewOrRC $CurrentPreviewNumberVersion
# Examples: ".NET 10 Preview 1" and ".NET 10 Preview 2"
$previousDotNetFriendlyName = GetDotNetFriendlyName $PreviousDotNetVersion $PreviousPreviewOrRC $PreviousPreviewNumberVersion
$currentDotNetFriendlyName = GetDotNetFriendlyName $CurrentDotNetVersion $CurrentPreviewOrRC $CurrentPreviewNumberVersion
If (-Not $ExcludeNetCore)
{
ProcessSdk "NETCore" $PreviousNuGetFeed $CurrentNuGetFeed $apiDiffExe $currentDotNetFullName $AssembliesToExcludeFilePath $AttributesToExcludeFilePath $previousDotNetFriendlyName $currentDotNetFriendlyName $PreviousPackageVersion $CurrentPackageVersion
}
If (-Not $ExcludeAspNetCore)
{
ProcessSdk "AspNetCore" $PreviousNuGetFeed $CurrentNuGetFeed $apiDiffExe $currentDotNetFullName $AssembliesToExcludeFilePath $AttributesToExcludeFilePath $previousDotNetFriendlyName $currentDotNetFriendlyName $PreviousPackageVersion $CurrentPackageVersion
}
If (-Not $ExcludeWindowsDesktop)
{
ProcessSdk "WindowsDesktop" $PreviousNuGetFeed $CurrentNuGetFeed $apiDiffExe $currentDotNetFullName $AssembliesToExcludeFilePath $AttributesToExcludeFilePath $previousDotNetFriendlyName $currentDotNetFriendlyName $PreviousPackageVersion $CurrentPackageVersion
}
CreateReadme $previewFolderPath $currentDotNetFriendlyName $currentDotNetFullName
#####################
### End Execution ###
#####################