From 0045cbd078fc7e0df816ebe3895d39b90dac3507 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Thu, 27 Feb 2025 13:08:42 -0800 Subject: [PATCH 1/7] New powershell script --- release-notes/RunApiDiff2.md | 25 ++ release-notes/RunApiDiff2.ps1 | 646 ++++++++++++++++++++++++++++++++++ 2 files changed, 671 insertions(+) create mode 100644 release-notes/RunApiDiff2.md create mode 100644 release-notes/RunApiDiff2.ps1 diff --git a/release-notes/RunApiDiff2.md b/release-notes/RunApiDiff2.md new file mode 100644 index 0000000000..800eddaab1 --- /dev/null +++ b/release-notes/RunApiDiff2.md @@ -0,0 +1,25 @@ +# RunApiDiff2 Script + +The [`RunApiDiff2.ps1`](./RunApiDiff2.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. + +## Instructions + +1. Clone the dotnet/sdk repo. Let's assume you clone it into `D:\sdk`. +2. Clone the dotnet/core repo. Let's assume you clone it into `D:\core`. +3. Create a temporary directory. Let's assume you create it in `D:\tmp`. +4. Run the command. Execution example: + +```powershell +.\RunApiDiff2.ps1 ` + -PreviousDotNetVersion 10.0 ` + -PreviousPreviewOrRC preview ` + -PreviousPreviewNumberVersion 1 ` + -CurrentDotNetVersion 10.0 ` + -CurrentPreviewOrRC preview ` + -CurrentPreviewNumberVersion 2 ` + -CoreRepo D:\core\ ` + -SdkRepo D:\sdk\ ` + -TmpFolder D:\tmp\ +``` + +Example of what this script generates: [API diff between .NET 10.0 Preview1 and .NET 10 Preview2](https://github.com/dotnet/core/pull/9771) diff --git a/release-notes/RunApiDiff2.ps1 b/release-notes/RunApiDiff2.ps1 new file mode 100644 index 0000000000..4a553f2174 --- /dev/null +++ b/release-notes/RunApiDiff2.ps1 @@ -0,0 +1,646 @@ +# 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. + +# Usage: + +# RunApiDiff2.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. +# -SdkRepo : The full path to your local clone of the dotnet/sdk 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. +# -UseNuGet : By default, the feed used is https://dnceng.pkgs.visualstudio.com/public/_packaging/dotnet10/nuget/v3/index.json , but if this is set to true, the feed used is https://api.nuget.org/v3/index.json + +# Example: +# .\RunApiDiff2.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\ + +# TODO: SDK Repo argument should go away, the tool will be available in the dotnet10 feed after the PR gets merged. + +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] + $SdkRepo #"D:\\sdk" # TODO: DELETE AFTER MERGING PR, REPLACE WITH DOWNLOADING TOOL FROM dotnet10 FEED +, + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] + $TmpFolder #"D:\tmp" +, + [Parameter(Mandatory=$false)] + [ValidateNotNullOrEmpty()] + [string] + $AttributesToExcludeFilePath = "ApiDiffAttributesToExclude.txt" +, + [Parameter(Mandatory=$false)] + [bool] + $UseNuGet = $false +) + +### 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 RunApiDiff2 +{ + 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] + $attributesToExclude + ) + + VerifyPathOrExit $apiDiffExe + VerifyPathOrExit $beforeFolder + VerifyPathOrExit $afterFolder + + # All arguments: + # "https://github.com/dotnet/sdk/tree/main/src/Compatibility/ApiDiff/Microsoft.DotNet.ApiDiff.Tool/Program.cs" + + RunCommand "$apiDiffExe -b $beforeFolder -a $afterFolder -o $outputFolder -tc $tableOfContentsFileNamePrefix -eattrs '$attributesToExclude'" +} + +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 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)] + [bool] + $useNuget + , + [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 + , + [ref] + $resultingPath + ) + + $fullSdkName = "Microsoft.$sdkName.App" + $destinationFolder = [IO.Path]::Combine($TmpFolder, "$fullSdkName.$beforeOrAfter") + RecreateFolder $destinationFolder + + $refPackageName = "$fullSdkName.Ref" + + $nugetSource = $useNuget ? "https://api.nuget.org/v3/index.json" : "https://dnceng.pkgs.visualstudio.com/public/_packaging/dotnet10/nuget/v3/index.json" + + $searchTerm = "" + If ($previewOrRC -eq "ga") + { + $searchTerm = "$dotNetversion.$previewNumberVersion" + } + ElseIf (-Not ([System.String]::IsNullOrWhiteSpace($previewOrRC)) -And -Not ([System.String]::IsNullOrWhiteSpace($previewNumberVersion))) + { + $searchTerm = "$dotNetversion.*-$previewOrRC.$previewNumberVersion*" + } + + $results = Find-Package -AllVersions -Source $nugetSource -Name $refPackageName -AllowPrereleaseVersions | Where-Object -Property Version -Like $searchTerm | Sort-Object Version -Descending + + If ($results.Count -eq 0) + { + Write-Error "No NuGet packages found with search term '$searchTerm'." -ErrorAction Stop + } + + $version = $results[0].Version + $nupkgFile = [IO.Path]::Combine($TmpFolder, "$refPackageName.$version.nupkg") + + If (-Not(Test-Path -Path $nupkgFile)) + { + $href = $results[0].Links | Where-Object -Property Relationship -Eq "icon" | Select-Object -ExpandProperty HRef + $link = $href.AbsoluteUri.Replace("?extract=Icon.png", "") + + $nupkgUrl = $useNuget ? "https://www.nuget.org/api/v2/package/$refPackageName/$version" : $link + + Write-Color yellow "Downloading '$nupkgUrl' to '$nupkgFile'..." + 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 GetAttributesToExclude +{ + Param ( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] + $filePath + ) + + VerifyPathOrExit $filePath + + $attributesToExclude = (Get-Content -Path $filePath) -join "," + Return $attributesToExclude +} + +### Execution ### + +## 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") + +$currentDotNetFullName = GetDotNetFullName $IsComparingReleases $CurrentDotNetVersion $CurrentPreviewOrRC $CurrentPreviewNumberVersion + + +## Check folders passed as parameters exist + +VerifyPathOrExit $CoreRepo +VerifyPathOrExit $SdkRepo +VerifyPathOrExit $TmpFolder + + +## Download the NuGet packages + +# NETCore +$netCoreBeforeDllFolder = "" +DownloadPackage $UseNuget "NETCore" "Before" $PreviousDotNetVersion $PreviousPreviewOrRC $PreviousPreviewNumberVersion ([ref]$netCoreBeforeDllFolder) +VerifyPathOrExit $netCoreBeforeDllFolder + +$netCoreAfterDllFolder = "" +DownloadPackage $UseNuget "NETCore" "After" $CurrentDotNetVersion $CurrentPreviewOrRC $CurrentPreviewNumberVersion ([ref]$netCoreAfterDllFolder) +VerifyPathOrExit $netCoreAfterDllFolder + +# AspNetCore +$aspNetCoreBeforeDllFolder = "" +DownloadPackage $UseNuget "AspNetCore" "Before" $PreviousDotNetVersion $PreviousPreviewOrRC $PreviousPreviewNumberVersion ([ref]$aspNetCoreBeforeDllFolder) +VerifyPathOrExit $aspNetCoreBeforeDllFolder + +$aspNetCoreAfterDllFolder = "" +DownloadPackage $UseNuget "AspNetCore" "After" $CurrentDotNetVersion $CurrentPreviewOrRC $CurrentPreviewNumberVersion ([ref]$aspNetCoreAfterDllFolder) +VerifyPathOrExit $aspNetCoreAfterDllFolder + +# WindowsDesktop +$windowsDesktopBeforeDllFolder = "" +DownloadPackage $UseNuget "WindowsDesktop" "Before" $PreviousDotNetVersion $PreviousPreviewOrRC $PreviousPreviewNumberVersion ([ref]$windowsDesktopBeforeDllFolder) +VerifyPathOrExit $windowsDesktopBeforeDllFolder + +$windowsDesktopAfterDllFolder = "" +DownloadPackage $UseNuget "WindowsDesktop" "After" $CurrentDotNetVersion $CurrentPreviewOrRC $CurrentPreviewNumberVersion ([ref]$windowsDesktopAfterDllFolder) +VerifyPathOrExit $windowsDesktopAfterDllFolder + + +## Ensure ApiDiff artifacts exist + +$apiDiffProjectPath = [IO.Path]::Combine($SdkRepo, "src", "Compatibility", "ApiDiff", "Microsoft.DotNet.ApiDiff.Tool", "Microsoft.DotNet.ApiDiff.Tool.csproj") +$apiDiffArtifactsPath = [IO.Path]::Combine($SdkRepo , "artifacts", "bin", "Microsoft.DotNet.ApiDiff.Tool") +$apiDiffExe = [IO.Path]::Combine($apiDiffArtifactsPath, "Release", "net8.0", "Microsoft.DotNet.ApiDiff.Tool.exe") +ReBuildIfExeNotFound $apiDiffExe $apiDiffProjectPath $apiDiffArtifactsPath + +## Recreate api-diff folder in core repo folder + +$previewFolderPath = GetPreviewFolderPath $CoreRepo $CurrentDotNetVersion $CurrentPreviewOrRC $CurrentPreviewNumberVersion $IsComparingReleases +Write-Color cyan "Checking existing diff folder: $previewFolderPath" +RecreateFolder $previewFolderPath + + +## Create subfolders + +# NETCore +$netCoreTargetFolder = [IO.Path]::Combine($previewFolderPath, "Microsoft.NETCore.App") +RecreateFolder $netCoreTargetFolder + +#AspNetCore +$aspNetCoreTargetFolder = [IO.Path]::Combine($previewFolderPath, "Microsoft.AspNetCore.App") +RecreateFolder $aspNetCoreTargetFolder + +# WindowsDesktop +$windowsDesktopTargetFolder = [IO.Path]::Combine($previewFolderPath, "Microsoft.WindowsDesktop.App") +RecreateFolder $windowsDesktopTargetFolder + + +## Run the ApiDiff commands + +$attributesToExclude = GetAttributesToExclude $AttributesToExcludeFilePath + +RunApiDiff2 $apiDiffExe $netCoreTargetFolder $netCoreBeforeDllFolder $netCoreAfterDllFolder $currentDotNetFullName $attributesToExclude +RunApiDiff2 $apiDiffExe $aspNetCoreTargetFolder $aspNetCoreBeforeDllFolder $aspNetCoreAfterDllFolder $currentDotNetFullName $attributesToExclude +RunApiDiff2 $apiDiffExe $windowsDesktopTargetFolder $windowsDesktopBeforeDllFolder $windowsDesktopAfterDllFolder $currentDotNetFullName $attributesToExclude + +$currentDotNetFriendlyName = GetDotNetFriendlyName $CurrentDotNetVersion $CurrentPreviewOrRC $CurrentPreviewNumberVersion + +CreateReadme $previewFolderPath $currentDotNetFriendlyName $currentDotNetFullName From 4d6b085ba40e77a79e6dd39a239c47a8dfe0b659 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Thu, 27 Feb 2025 13:09:04 -0800 Subject: [PATCH 2/7] Text file with attribute APIs to exclude by default --- release-notes/ApiDiffAttributesToExclude.txt | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 release-notes/ApiDiffAttributesToExclude.txt diff --git a/release-notes/ApiDiffAttributesToExclude.txt b/release-notes/ApiDiffAttributesToExclude.txt new file mode 100644 index 0000000000..3ed785dc8d --- /dev/null +++ b/release-notes/ApiDiffAttributesToExclude.txt @@ -0,0 +1,6 @@ +T:System.AttributeUsageAttribute +T:System.ComponentModel.EditorBrowsableAttribute +T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute +T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute +T:System.Windows.Markup.ContentWrapperAttribute +T:System.Windows.TemplatePartAttribute \ No newline at end of file From 9b19f887eff9822194d28a81613029bf80fa52a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Thu, 27 Feb 2025 16:41:00 -0800 Subject: [PATCH 3/7] Add beforeFriendlyName and afterFriendlyName arguments. Pass the correct strings to the api diff tool. Add better logic to determine root of failure when packages are not found. --- release-notes/RunApiDiff2.ps1 | 40 +++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/release-notes/RunApiDiff2.ps1 b/release-notes/RunApiDiff2.ps1 index 4a553f2174..cdfe636aed 100644 --- a/release-notes/RunApiDiff2.ps1 +++ b/release-notes/RunApiDiff2.ps1 @@ -372,6 +372,16 @@ Function RunApiDiff2 [ValidateNotNullOrEmpty()] [string] $attributesToExclude + , + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string] + $beforeFriendlyName + , + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string] + $afterFriendlyName ) VerifyPathOrExit $apiDiffExe @@ -381,7 +391,7 @@ Function RunApiDiff2 # All arguments: # "https://github.com/dotnet/sdk/tree/main/src/Compatibility/ApiDiff/Microsoft.DotNet.ApiDiff.Tool/Program.cs" - RunCommand "$apiDiffExe -b $beforeFolder -a $afterFolder -o $outputFolder -tc $tableOfContentsFileNamePrefix -eattrs '$attributesToExclude'" + RunCommand "$apiDiffExe -b '$beforeFolder' -a '$afterFolder' -o '$outputFolder' -tc '$tableOfContentsFileNamePrefix' -eattrs '$attributesToExclude' -bfn '$beforeFriendlyName' -afn '$afterFriendlyName'" } Function CreateReadme @@ -496,7 +506,7 @@ Function DownloadPackage $refPackageName = "$fullSdkName.Ref" - $nugetSource = $useNuget ? "https://api.nuget.org/v3/index.json" : "https://dnceng.pkgs.visualstudio.com/public/_packaging/dotnet10/nuget/v3/index.json" + $feed = $useNuget ? "https://api.nuget.org/v3/index.json" : "https://dnceng.pkgs.visualstudio.com/public/_packaging/dotnet10/nuget/v3/index.json" $searchTerm = "" If ($previewOrRC -eq "ga") @@ -508,7 +518,16 @@ Function DownloadPackage $searchTerm = "$dotNetversion.*-$previewOrRC.$previewNumberVersion*" } - $results = Find-Package -AllVersions -Source $nugetSource -Name $refPackageName -AllowPrereleaseVersions | Where-Object -Property Version -Like $searchTerm | Sort-Object Version -Descending + $foundPackages = Find-Package -AllVersions -Source $feed -Name $refPackageName -AllowPrereleaseVersions -ErrorAction Continue + + If ($foundPackages.Count -eq 0) + { + Write-Error "No NuGet packages found with ref package name '$refPackageName' in feed '$feed'" + Get-PackageSource -Name $refPackageName | Format-Table -Property Name, SourceUri + Write-Error "Exiting" -ErrorAction Stop + } + + $results = $foundPackages | Where-Object -Property Version -Like $searchTerm | Sort-Object Version -Descending If ($results.Count -eq 0) { @@ -564,9 +583,6 @@ Function GetAttributesToExclude # True when comparing 8.0 GA with 9.0 GA $IsComparingReleases = ($PreviousDotNetVersion -Ne $CurrentDotNetVersion) -And ($PreviousPreviewOrRC -Eq "ga") -And ($CurrentPreviewOrRC -eq "ga") -$currentDotNetFullName = GetDotNetFullName $IsComparingReleases $CurrentDotNetVersion $CurrentPreviewOrRC $CurrentPreviewNumberVersion - - ## Check folders passed as parameters exist VerifyPathOrExit $CoreRepo @@ -635,12 +651,18 @@ RecreateFolder $windowsDesktopTargetFolder ## Run the ApiDiff commands +# Comma separated docIDs of attribute types $attributesToExclude = GetAttributesToExclude $AttributesToExcludeFilePath -RunApiDiff2 $apiDiffExe $netCoreTargetFolder $netCoreBeforeDllFolder $netCoreAfterDllFolder $currentDotNetFullName $attributesToExclude -RunApiDiff2 $apiDiffExe $aspNetCoreTargetFolder $aspNetCoreBeforeDllFolder $aspNetCoreAfterDllFolder $currentDotNetFullName $attributesToExclude -RunApiDiff2 $apiDiffExe $windowsDesktopTargetFolder $windowsDesktopBeforeDllFolder $windowsDesktopAfterDllFolder $currentDotNetFullName $attributesToExclude +# 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 +RunApiDiff2 $apiDiffExe $netCoreTargetFolder $netCoreBeforeDllFolder $netCoreAfterDllFolder $currentDotNetFullName $attributesToExclude $previousDotNetFriendlyName $currentDotNetFriendlyName +RunApiDiff2 $apiDiffExe $aspNetCoreTargetFolder $aspNetCoreBeforeDllFolder $aspNetCoreAfterDllFolder $currentDotNetFullName $attributesToExclude $previousDotNetFriendlyName $currentDotNetFriendlyName +RunApiDiff2 $apiDiffExe $windowsDesktopTargetFolder $windowsDesktopBeforeDllFolder $windowsDesktopAfterDllFolder $currentDotNetFullName $attributesToExclude $previousDotNetFriendlyName $currentDotNetFriendlyName + CreateReadme $previewFolderPath $currentDotNetFriendlyName $currentDotNetFullName From 4d0c79f7c76b63b08de76da05224777701243dbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Fri, 7 Mar 2025 15:45:29 -0800 Subject: [PATCH 4/7] Add assemblies to exclude --- release-notes/ApiDiffAssembliesToExclude.txt | 2 ++ release-notes/RunApiDiff2.ps1 | 37 ++++++++++++++------ 2 files changed, 28 insertions(+), 11 deletions(-) create mode 100644 release-notes/ApiDiffAssembliesToExclude.txt diff --git a/release-notes/ApiDiffAssembliesToExclude.txt b/release-notes/ApiDiffAssembliesToExclude.txt new file mode 100644 index 0000000000..079acb739f --- /dev/null +++ b/release-notes/ApiDiffAssembliesToExclude.txt @@ -0,0 +1,2 @@ +netstandard.dll +mscorlib.dll \ No newline at end of file diff --git a/release-notes/RunApiDiff2.ps1 b/release-notes/RunApiDiff2.ps1 index cdfe636aed..60f1797462 100644 --- a/release-notes/RunApiDiff2.ps1 +++ b/release-notes/RunApiDiff2.ps1 @@ -13,6 +13,7 @@ # -SdkRepo : The full path to your local clone of the dotnet/sdk 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. # -UseNuGet : By default, the feed used is https://dnceng.pkgs.visualstudio.com/public/_packaging/dotnet10/nuget/v3/index.json , but if this is set to true, the feed used is https://api.nuget.org/v3/index.json # Example: @@ -70,7 +71,13 @@ Param ( [ValidateNotNullOrEmpty()] [string] $AttributesToExcludeFilePath = "ApiDiffAttributesToExclude.txt" -, + , + [Parameter(Mandatory = $false)] + [ValidateNotNullOrEmpty()] + [string] + $AssembliesToExcludeFilePath = "ApiDiffAssembliesToExclude.txt" + , + [Parameter(Mandatory=$false)] [bool] $UseNuGet = $false @@ -367,7 +374,12 @@ Function RunApiDiff2 [ValidateNotNullOrEmpty()] [string] $tableOfContentsFileNamePrefix - , + , + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string] + $assembliesToExclude + , [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] @@ -391,7 +403,7 @@ Function RunApiDiff2 # All arguments: # "https://github.com/dotnet/sdk/tree/main/src/Compatibility/ApiDiff/Microsoft.DotNet.ApiDiff.Tool/Program.cs" - RunCommand "$apiDiffExe -b '$beforeFolder' -a '$afterFolder' -o '$outputFolder' -tc '$tableOfContentsFileNamePrefix' -eattrs '$attributesToExclude' -bfn '$beforeFriendlyName' -afn '$afterFriendlyName'" + RunCommand "$apiDiffExe -b '$beforeFolder' -a '$afterFolder' -o '$outputFolder' -tc '$tableOfContentsFileNamePrefix' -eas '$assembliesToExclude' -eattrs '$attributesToExclude' -bfn '$beforeFriendlyName' -afn '$afterFriendlyName'" } Function CreateReadme @@ -561,7 +573,7 @@ Function DownloadPackage $resultingPath.value = $dllPath } -Function GetAttributesToExclude +Function GetFileLinesAsCommaSeparaterList { Param ( [Parameter(Mandatory=$true)] @@ -572,8 +584,8 @@ Function GetAttributesToExclude VerifyPathOrExit $filePath - $attributesToExclude = (Get-Content -Path $filePath) -join "," - Return $attributesToExclude + $lines = (Get-Content -Path $filePath) -join "," + Return $lines } ### Execution ### @@ -651,8 +663,11 @@ RecreateFolder $windowsDesktopTargetFolder ## Run the ApiDiff commands -# Comma separated docIDs of attribute types -$attributesToExclude = GetAttributesToExclude $AttributesToExcludeFilePath +# Comma separated docIDs of attribute types to exclude +$attributesToExclude = GetFileLinesAsCommaSeparaterList $AttributesToExcludeFilePath + +# Comma separated list of assembly names to exclude +$assembliesToExclude = GetFileLinesAsCommaSeparaterList $AssembliesToExcludeFilePath # Example: "10.0-preview2" $currentDotNetFullName = GetDotNetFullName $IsComparingReleases $CurrentDotNetVersion $CurrentPreviewOrRC $CurrentPreviewNumberVersion @@ -661,8 +676,8 @@ $currentDotNetFullName = GetDotNetFullName $IsComparingReleases $CurrentDotNetVe $previousDotNetFriendlyName = GetDotNetFriendlyName $PreviousDotNetVersion $PreviousPreviewOrRC $PreviousPreviewNumberVersion $currentDotNetFriendlyName = GetDotNetFriendlyName $CurrentDotNetVersion $CurrentPreviewOrRC $CurrentPreviewNumberVersion -RunApiDiff2 $apiDiffExe $netCoreTargetFolder $netCoreBeforeDllFolder $netCoreAfterDllFolder $currentDotNetFullName $attributesToExclude $previousDotNetFriendlyName $currentDotNetFriendlyName -RunApiDiff2 $apiDiffExe $aspNetCoreTargetFolder $aspNetCoreBeforeDllFolder $aspNetCoreAfterDllFolder $currentDotNetFullName $attributesToExclude $previousDotNetFriendlyName $currentDotNetFriendlyName -RunApiDiff2 $apiDiffExe $windowsDesktopTargetFolder $windowsDesktopBeforeDllFolder $windowsDesktopAfterDllFolder $currentDotNetFullName $attributesToExclude $previousDotNetFriendlyName $currentDotNetFriendlyName +RunApiDiff2 $apiDiffExe $netCoreTargetFolder $netCoreBeforeDllFolder $netCoreAfterDllFolder $currentDotNetFullName $assembliesToExclude $attributesToExclude $previousDotNetFriendlyName $currentDotNetFriendlyName +RunApiDiff2 $apiDiffExe $aspNetCoreTargetFolder $aspNetCoreBeforeDllFolder $aspNetCoreAfterDllFolder $currentDotNetFullName $assembliesToExclude $attributesToExclude $previousDotNetFriendlyName $currentDotNetFriendlyName +RunApiDiff2 $apiDiffExe $windowsDesktopTargetFolder $windowsDesktopBeforeDllFolder $windowsDesktopAfterDllFolder $currentDotNetFullName $assembliesToExclude $attributesToExclude $previousDotNetFriendlyName $currentDotNetFriendlyName CreateReadme $previewFolderPath $currentDotNetFriendlyName $currentDotNetFullName From 55028d0e8116ac0f0c86b32eb2a0fe6937226337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Thu, 27 Mar 2025 22:30:21 -0700 Subject: [PATCH 5/7] Remove extensions from assemblies to exclude --- release-notes/ApiDiffAssembliesToExclude.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release-notes/ApiDiffAssembliesToExclude.txt b/release-notes/ApiDiffAssembliesToExclude.txt index 079acb739f..4ec161b762 100644 --- a/release-notes/ApiDiffAssembliesToExclude.txt +++ b/release-notes/ApiDiffAssembliesToExclude.txt @@ -1,2 +1,2 @@ -netstandard.dll -mscorlib.dll \ No newline at end of file +netstandard +mscorlib \ No newline at end of file From cc9ff4429b55d1b972d840d63e4cfbc477240cb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Thu, 27 Mar 2025 22:30:35 -0700 Subject: [PATCH 6/7] Add options to exclude a particular sdk --- release-notes/RunApiDiff2.ps1 | 441 +++++++++++++++++----------------- 1 file changed, 227 insertions(+), 214 deletions(-) diff --git a/release-notes/RunApiDiff2.ps1 b/release-notes/RunApiDiff2.ps1 index 60f1797462..3884dbbcb9 100644 --- a/release-notes/RunApiDiff2.ps1 +++ b/release-notes/RunApiDiff2.ps1 @@ -15,6 +15,9 @@ # -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. # -UseNuGet : By default, the feed used is https://dnceng.pkgs.visualstudio.com/public/_packaging/dotnet10/nuget/v3/index.json , but if this is set to true, the feed used is https://api.nuget.org/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. # Example: # .\RunApiDiff2.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\ @@ -22,52 +25,52 @@ # TODO: SDK Repo argument should go away, the tool will be available in the dotnet10 feed after the PR gets merged. Param ( - [Parameter(Mandatory=$true)] + [Parameter(Mandatory = $true)] [ValidatePattern("\d+\.\d")] [string] $PreviousDotNetVersion # 7.0, 8.0, 9.0, ... -, - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [string] [ValidateSet("preview", "rc", "ga")] $PreviousPreviewOrRC -, - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidatePattern("(\d+)?")] [string] $PreviousPreviewNumberVersion # 0, 1, 2, 3, ... -, - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidatePattern("\d+\.\d")] [string] $CurrentDotNetVersion # 7.0, 8.0, 9.0, ... -, - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [string] [ValidateSet("preview", "rc", "ga")] $CurrentPreviewOrRC -, - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidatePattern("(\d+)?")] [string] $CurrentPreviewNumberVersion # 0, 1, 2, 3, ... -, - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $CoreRepo #"D:\\core" -, - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $SdkRepo #"D:\\sdk" # TODO: DELETE AFTER MERGING PR, REPLACE WITH DOWNLOADING TOOL FROM dotnet10 FEED -, - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $TmpFolder #"D:\tmp" -, - [Parameter(Mandatory=$false)] + , + [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string] $AttributesToExcludeFilePath = "ApiDiffAttributesToExclude.txt" @@ -77,16 +80,28 @@ Param ( [string] $AssembliesToExcludeFilePath = "ApiDiffAssembliesToExclude.txt" , - - [Parameter(Mandatory=$false)] + [Parameter(Mandatory = $false)] [bool] $UseNuGet = $false + , + [Parameter(Mandatory = $false)] + [bool] + $ExcludeNetCore = $false + , + [Parameter(Mandatory = $false)] + [bool] + $ExcludeAspNetCore = $false + , + [Parameter(Mandatory = $false)] + [bool] + $ExcludeWindowsDesktop = $false ) -### Functions ### +####################### +### Start Functions ### +####################### -Function Write-Color -{ +Function Write-Color { Param ( [ValidateNotNullOrEmpty()] [string] $newColor @@ -95,53 +110,46 @@ Function Write-Color $oldColor = $host.UI.RawUI.ForegroundColor $host.UI.RawUI.ForegroundColor = $newColor - If ($args) - { + If ($args) { Write-Output $args } - Else - { + Else { $input | Write-Output } $host.UI.RawUI.ForegroundColor = $oldColor } -Function VerifyPathOrExit -{ +Function VerifyPathOrExit { Param ( - [Parameter(Mandatory=$true)] + [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $path ) - If (-Not (Test-Path -Path $path)) - { + If (-Not (Test-Path -Path $path)) { Write-Error "The path '$path' does not exist." -ErrorAction Stop } } -Function RemoveFolderIfExists -{ +Function RemoveFolderIfExists { Param ( - [Parameter(Mandatory=$true)] + [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $path ) - If (Test-Path -Path $path) - { + If (Test-Path -Path $path) { Write-Color yellow "Removing existing folder: $path" Remove-Item -Recurse -Path $path } } -Function RecreateFolder -{ +Function RecreateFolder { Param ( - [Parameter(Mandatory=$true)] + [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $path @@ -153,10 +161,9 @@ Function RecreateFolder New-Item -ItemType Directory -Path $path } -Function VerifyCountDlls -{ +Function VerifyCountDlls { Param ( - [Parameter(Mandatory=$true)] + [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $path @@ -164,17 +171,15 @@ Function VerifyCountDlls VerifyPathOrExit $path - $count=(Get-ChildItem -Path $path -Filter "*.dll" | Measure-Object).Count - If ($count -eq 0) - { + $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 -{ +Function RunCommand { Param ( - [Parameter(Mandatory=$True)] + [Parameter(Mandatory = $True)] [ValidateNotNullOrEmpty()] [string] $command @@ -184,38 +189,34 @@ Function RunCommand Invoke-Expression "$command" } -Function GetDotNetFullName -{ +Function GetDotNetFullName { Param ( - [Parameter(Mandatory=$true)] + [Parameter(Mandatory = $true)] [bool] $IsComparingReleases - , - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidatePattern("\d+\.\d")] [string] $dotNetVersion # 7.0, 8.0, 9.0, ... - , - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [string] [ValidateSet("preview", "rc", "ga")] $previewOrRC - , - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidatePattern("(\d+)?")] [string] $previewNumberVersion # 0, 1, 2, 3, ... ) - If ($IsComparingReleases) - { + If ($IsComparingReleases) { Return "$dotNetVersion.$previewNumberVersion" } - If ($previewOrRC -eq "ga") - { - If ($previewNumberVersion -eq "0") - { + If ($previewOrRC -eq "ga") { + If ($previewNumberVersion -eq "0") { # Example: Don't return "7.0-ga0", instead just return "7.0-ga" Return "$dotNetVersion-$previewOrRC" } @@ -228,39 +229,34 @@ Function GetDotNetFullName Return "$dotNetVersion-$previewOrRC$previewNumberVersion" } -Function GetDotNetFriendlyName -{ +Function GetDotNetFriendlyName { Param ( - [Parameter(Mandatory=$true)] + [Parameter(Mandatory = $true)] [ValidatePattern("\d+\.\d")] [string] $DotNetVersion # 7.0, 8.0, 9.0, ... - , - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [string] [ValidateSet("preview", "rc", "ga")] $PreviewOrRC - , - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidatePattern("(\d+)?")] [string] $PreviewNumberVersion # 0, 1, 2, 3, ... ) $friendlyPreview = "" - If ($PreviewOrRC -eq "preview") - { + If ($PreviewOrRC -eq "preview") { $friendlyPreview = "Preview" } - ElseIf ($PreviewOrRC -eq "rc") - { + ElseIf ($PreviewOrRC -eq "rc") { $friendlyPreview = "RC" } - ElseIf ($PreviewOrRC -eq "ga") - { + ElseIf ($PreviewOrRC -eq "ga") { $friendlyPreview = "GA" - If ($PreviewNumberVersion -eq 0) - { + If ($PreviewNumberVersion -eq 0) { # Example: Don't return "7.0 GA 0", instead just return "7.0 GA" Return ".NET $DotNetVersion $friendlyPreview" } @@ -273,29 +269,26 @@ Function GetDotNetFriendlyName Return ".NET $DotNetVersion $friendlyPreview $PreviewNumberVersion" } -Function GetPreviewOrRCFolderName -{ +Function GetPreviewOrRCFolderName { Param ( - [Parameter(Mandatory=$true)] + [Parameter(Mandatory = $true)] [ValidatePattern("\d+\.\d")] [string] $dotNetVersion # 7.0, 8.0, 9.0, ... - , - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [string] [ValidateSet("preview", "rc", "ga")] $previewOrRC - , - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidatePattern("(\d+)?")] [string] $previewNumberVersion # 0, 1, 2, 3, ... ) - If ($previewOrRC -eq "ga") - { - If ($previewNumberVersion -eq "0") - { + If ($previewOrRC -eq "ga") { + If ($previewNumberVersion -eq "0") { # return "ga", not "ga0" Return $previewOrRC } @@ -307,30 +300,29 @@ Function GetPreviewOrRCFolderName Return "$previewOrRC$previewNumberVersion" } -Function GetPreviewFolderPath -{ +Function GetPreviewFolderPath { Param ( - [Parameter(Mandatory=$true)] + [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $rootFolder #"D:\\core" - , - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidatePattern("\d+\.\d")] [string] $dotNetVersion # 7.0, 8.0, 9.0, ... - , - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [string] [ValidateSet("preview", "rc", "ga")] $previewOrRC - , - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidatePattern("(\d+)?")] [string] $previewNumberVersion # 0, 1, 2, 3, ... - , - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [bool] $IsComparingReleases # True when comparing 8.0 GA with 9.0 GA ) @@ -338,8 +330,7 @@ Function GetPreviewFolderPath $prefixFolder = [IO.Path]::Combine($rootFolder, "release-notes", $dotNetVersion) $apiDiffFolderName = "api-diff" - If ($IsComparingReleases) - { + If ($IsComparingReleases) { Return [IO.Path]::Combine($prefixFolder, "$dotNetVersion.$previewNumberVersion", $apiDiffFolderName) } @@ -347,30 +338,29 @@ Function GetPreviewFolderPath Return [IO.Path]::Combine($prefixFolder, "preview", $previewOrRCFolderName, $apiDiffFolderName) } -Function RunApiDiff2 -{ +Function RunApiDiff2 { Param ( - [Parameter(Mandatory=$true)] + [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $apiDiffExe - , - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $outputFolder - , - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $beforeFolder - , - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $afterFolder - , - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $tableOfContentsFileNamePrefix @@ -380,7 +370,7 @@ Function RunApiDiff2 [string] $assembliesToExclude , - [Parameter(Mandatory=$true)] + [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $attributesToExclude @@ -406,28 +396,26 @@ Function RunApiDiff2 RunCommand "$apiDiffExe -b '$beforeFolder' -a '$afterFolder' -o '$outputFolder' -tc '$tableOfContentsFileNamePrefix' -eas '$assembliesToExclude' -eattrs '$attributesToExclude' -bfn '$beforeFriendlyName' -afn '$afterFriendlyName'" } -Function CreateReadme -{ +Function CreateReadme { Param ( - [Parameter(Mandatory=$true)] + [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $previewFolderPath - , - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $dotNetFriendlyName - , - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $dotNetFullName ) - $readmePath=[IO.Path]::Combine($previewFolderPath, "README.md") - If (Test-Path -Path $readmePath) - { + $readmePath = [IO.Path]::Combine($previewFolderPath, "README.md") + If (Test-Path -Path $readmePath) { Remove-Item -Path $readmePath } New-Item -ItemType File $readmePath @@ -441,20 +429,19 @@ Function CreateReadme Add-Content $readmePath "- [Microsoft.WindowsDesktop.App](./Microsoft.WindowsDesktop.App/$dotNetFullName.md)" } -Function RebuildIfExeNotFound -{ +Function RebuildIfExeNotFound { Param ( - [Parameter(Mandatory=$true)] + [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $exePath - , - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $projectPath - , - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $artifactsPath @@ -462,8 +449,7 @@ Function RebuildIfExeNotFound VerifyPathOrExit $projectPath - If (-Not (Test-Path -Path $exePath)) - { + If (-Not (Test-Path -Path $exePath)) { # Building the project Write-Color cyan "Building project '$projectPath'" @@ -475,39 +461,38 @@ Function RebuildIfExeNotFound } } -Function DownloadPackage -{ +Function DownloadPackage { Param ( - [Parameter(Mandatory=$true)] + [Parameter(Mandatory = $true)] [bool] $useNuget - , - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidateSet("NETCore", "AspNetCore", "WindowsDesktop")] [string] $sdkName - , - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidateSet("Before", "After")] [string] $beforeOrAfter - , - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidatePattern("\d+\.\d")] [string] $dotNetVersion - , - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidateSet("preview", "rc", "ga")] [string] $previewOrRC - , - [Parameter(Mandatory=$true)] + , + [Parameter(Mandatory = $true)] [ValidatePattern("(\d+)?")] [string] $previewNumberVersion - , + , [ref] $resultingPath ) @@ -521,19 +506,16 @@ Function DownloadPackage $feed = $useNuget ? "https://api.nuget.org/v3/index.json" : "https://dnceng.pkgs.visualstudio.com/public/_packaging/dotnet10/nuget/v3/index.json" $searchTerm = "" - If ($previewOrRC -eq "ga") - { + If ($previewOrRC -eq "ga") { $searchTerm = "$dotNetversion.$previewNumberVersion" } - ElseIf (-Not ([System.String]::IsNullOrWhiteSpace($previewOrRC)) -And -Not ([System.String]::IsNullOrWhiteSpace($previewNumberVersion))) - { + ElseIf (-Not ([System.String]::IsNullOrWhiteSpace($previewOrRC)) -And -Not ([System.String]::IsNullOrWhiteSpace($previewNumberVersion))) { $searchTerm = "$dotNetversion.*-$previewOrRC.$previewNumberVersion*" } $foundPackages = Find-Package -AllVersions -Source $feed -Name $refPackageName -AllowPrereleaseVersions -ErrorAction Continue - If ($foundPackages.Count -eq 0) - { + If ($foundPackages.Count -eq 0) { Write-Error "No NuGet packages found with ref package name '$refPackageName' in feed '$feed'" Get-PackageSource -Name $refPackageName | Format-Table -Property Name, SourceUri Write-Error "Exiting" -ErrorAction Stop @@ -541,16 +523,14 @@ Function DownloadPackage $results = $foundPackages | Where-Object -Property Version -Like $searchTerm | Sort-Object Version -Descending - If ($results.Count -eq 0) - { + If ($results.Count -eq 0) { Write-Error "No NuGet packages found with search term '$searchTerm'." -ErrorAction Stop } $version = $results[0].Version $nupkgFile = [IO.Path]::Combine($TmpFolder, "$refPackageName.$version.nupkg") - If (-Not(Test-Path -Path $nupkgFile)) - { + If (-Not(Test-Path -Path $nupkgFile)) { $href = $results[0].Links | Where-Object -Property Relationship -Eq "icon" | Select-Object -ExpandProperty HRef $link = $href.AbsoluteUri.Replace("?extract=Icon.png", "") @@ -560,8 +540,7 @@ Function DownloadPackage Invoke-WebRequest -Uri $nupkgUrl -OutFile $nupkgFile VerifyPathOrExit $nupkgFile } - Else - { + Else { Write-Color green "File '$nupkgFile' already exists locally. Skipping re-download." } @@ -573,10 +552,9 @@ Function DownloadPackage $resultingPath.value = $dllPath } -Function GetFileLinesAsCommaSeparaterList -{ +Function GetFileLinesAsCommaSeparaterList { Param ( - [Parameter(Mandatory=$true)] + [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $filePath @@ -588,48 +566,79 @@ Function GetFileLinesAsCommaSeparaterList Return $lines } -### Execution ### +Function ProcessSdk +{ + Param( + [Parameter(Mandatory = $false)] + [ValidateNotNullOrEmpty()] + [string] + $sdkName + , + [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 + ) -## Generate strings with no whitespace + $beforeDllFolder = "" + DownloadPackage $UseNuget $sdkName "Before" $PreviousDotNetVersion $PreviousPreviewOrRC $PreviousPreviewNumberVersion ([ref]$beforeDllFolder) + VerifyPathOrExit $beforeDllFolder -# True when comparing 8.0 GA with 9.0 GA -$IsComparingReleases = ($PreviousDotNetVersion -Ne $CurrentDotNetVersion) -And ($PreviousPreviewOrRC -Eq "ga") -And ($CurrentPreviewOrRC -eq "ga") + $afterDllFolder = "" + DownloadPackage $UseNuget $sdkName "After" $CurrentDotNetVersion $CurrentPreviewOrRC $CurrentPreviewNumberVersion ([ref]$afterDllFolder) + VerifyPathOrExit $afterDllFolder -## Check folders passed as parameters exist + $targetFolder = [IO.Path]::Combine($previewFolderPath, "Microsoft.$adkName.App") + RecreateFolder $targetFolder -VerifyPathOrExit $CoreRepo -VerifyPathOrExit $SdkRepo -VerifyPathOrExit $TmpFolder + RunApiDiff2 $apiDiffExe $targetFolder $beforeDllFolder $afterDllFolder $currentDotNetFullName $assembliesToExclude $attributesToExclude $previousDotNetFriendlyName $currentDotNetFriendlyName +} +##################### +### End Functions ### +##################### -## Download the NuGet packages +####################### +### Start Execution ### +####################### -# NETCore -$netCoreBeforeDllFolder = "" -DownloadPackage $UseNuget "NETCore" "Before" $PreviousDotNetVersion $PreviousPreviewOrRC $PreviousPreviewNumberVersion ([ref]$netCoreBeforeDllFolder) -VerifyPathOrExit $netCoreBeforeDllFolder -$netCoreAfterDllFolder = "" -DownloadPackage $UseNuget "NETCore" "After" $CurrentDotNetVersion $CurrentPreviewOrRC $CurrentPreviewNumberVersion ([ref]$netCoreAfterDllFolder) -VerifyPathOrExit $netCoreAfterDllFolder +## Generate strings with no whitespace -# AspNetCore -$aspNetCoreBeforeDllFolder = "" -DownloadPackage $UseNuget "AspNetCore" "Before" $PreviousDotNetVersion $PreviousPreviewOrRC $PreviousPreviewNumberVersion ([ref]$aspNetCoreBeforeDllFolder) -VerifyPathOrExit $aspNetCoreBeforeDllFolder +# True when comparing 8.0 GA with 9.0 GA +$IsComparingReleases = ($PreviousDotNetVersion -Ne $CurrentDotNetVersion) -And ($PreviousPreviewOrRC -Eq "ga") -And ($CurrentPreviewOrRC -eq "ga") -$aspNetCoreAfterDllFolder = "" -DownloadPackage $UseNuget "AspNetCore" "After" $CurrentDotNetVersion $CurrentPreviewOrRC $CurrentPreviewNumberVersion ([ref]$aspNetCoreAfterDllFolder) -VerifyPathOrExit $aspNetCoreAfterDllFolder -# WindowsDesktop -$windowsDesktopBeforeDllFolder = "" -DownloadPackage $UseNuget "WindowsDesktop" "Before" $PreviousDotNetVersion $PreviousPreviewOrRC $PreviousPreviewNumberVersion ([ref]$windowsDesktopBeforeDllFolder) -VerifyPathOrExit $windowsDesktopBeforeDllFolder +## Check folders passed as parameters exist -$windowsDesktopAfterDllFolder = "" -DownloadPackage $UseNuget "WindowsDesktop" "After" $CurrentDotNetVersion $CurrentPreviewOrRC $CurrentPreviewNumberVersion ([ref]$windowsDesktopAfterDllFolder) -VerifyPathOrExit $windowsDesktopAfterDllFolder +VerifyPathOrExit $CoreRepo +VerifyPathOrExit $SdkRepo +VerifyPathOrExit $TmpFolder ## Ensure ApiDiff artifacts exist @@ -639,26 +648,15 @@ $apiDiffArtifactsPath = [IO.Path]::Combine($SdkRepo , "artifacts", "bin", "Micro $apiDiffExe = [IO.Path]::Combine($apiDiffArtifactsPath, "Release", "net8.0", "Microsoft.DotNet.ApiDiff.Tool.exe") ReBuildIfExeNotFound $apiDiffExe $apiDiffProjectPath $apiDiffArtifactsPath + ## Recreate api-diff folder in core repo folder $previewFolderPath = GetPreviewFolderPath $CoreRepo $CurrentDotNetVersion $CurrentPreviewOrRC $CurrentPreviewNumberVersion $IsComparingReleases -Write-Color cyan "Checking existing diff folder: $previewFolderPath" -RecreateFolder $previewFolderPath - - -## Create subfolders - -# NETCore -$netCoreTargetFolder = [IO.Path]::Combine($previewFolderPath, "Microsoft.NETCore.App") -RecreateFolder $netCoreTargetFolder - -#AspNetCore -$aspNetCoreTargetFolder = [IO.Path]::Combine($previewFolderPath, "Microsoft.AspNetCore.App") -RecreateFolder $aspNetCoreTargetFolder - -# WindowsDesktop -$windowsDesktopTargetFolder = [IO.Path]::Combine($previewFolderPath, "Microsoft.WindowsDesktop.App") -RecreateFolder $windowsDesktopTargetFolder +If (-Not (Test-Path -Path $previewFolderPath)) +{ + Write-Color white "Creating new diff folder: $previewFolderPath" + New-Item -ItemType Directory -Path $previewFolderPath +} ## Run the ApiDiff commands @@ -676,8 +674,23 @@ $currentDotNetFullName = GetDotNetFullName $IsComparingReleases $CurrentDotNetVe $previousDotNetFriendlyName = GetDotNetFriendlyName $PreviousDotNetVersion $PreviousPreviewOrRC $PreviousPreviewNumberVersion $currentDotNetFriendlyName = GetDotNetFriendlyName $CurrentDotNetVersion $CurrentPreviewOrRC $CurrentPreviewNumberVersion -RunApiDiff2 $apiDiffExe $netCoreTargetFolder $netCoreBeforeDllFolder $netCoreAfterDllFolder $currentDotNetFullName $assembliesToExclude $attributesToExclude $previousDotNetFriendlyName $currentDotNetFriendlyName -RunApiDiff2 $apiDiffExe $aspNetCoreTargetFolder $aspNetCoreBeforeDllFolder $aspNetCoreAfterDllFolder $currentDotNetFullName $assembliesToExclude $attributesToExclude $previousDotNetFriendlyName $currentDotNetFriendlyName -RunApiDiff2 $apiDiffExe $windowsDesktopTargetFolder $windowsDesktopBeforeDllFolder $windowsDesktopAfterDllFolder $currentDotNetFullName $assembliesToExclude $attributesToExclude $previousDotNetFriendlyName $currentDotNetFriendlyName +If (-Not $ExcludeNetCore) +{ + ProcessSdk "NETCore" $apiDiffExe $currentDotNetFullName $assembliesToExclude $attributesToExclude $previousDotNetFriendlyName $currentDotNetFriendlyName +} + +If (-Not $ExcludeAspNetCore) +{ + ProcessSdk "AspNetCore" $apiDiffExe $currentDotNetFullName $assembliesToExclude $attributesToExclude $previousDotNetFriendlyName $currentDotNetFriendlyName +} + +If (-Not $ExcludeWindowsDesktop) +{ + ProcessSdk "WindowsDesktop" $apiDiffExe $currentDotNetFullName $assembliesToExclude $attributesToExclude $previousDotNetFriendlyName $currentDotNetFriendlyName +} CreateReadme $previewFolderPath $currentDotNetFriendlyName $currentDotNetFullName + +##################### +### End Execution ### +##################### \ No newline at end of file From f4414dce86bc4f4650214f0fb92ab1bfd37049a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?= <1175054+carlossanlop@users.noreply.github.com> Date: Thu, 27 Mar 2025 22:45:28 -0700 Subject: [PATCH 7/7] typo --- release-notes/RunApiDiff2.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release-notes/RunApiDiff2.ps1 b/release-notes/RunApiDiff2.ps1 index 3884dbbcb9..40daf32827 100644 --- a/release-notes/RunApiDiff2.ps1 +++ b/release-notes/RunApiDiff2.ps1 @@ -613,7 +613,7 @@ Function ProcessSdk DownloadPackage $UseNuget $sdkName "After" $CurrentDotNetVersion $CurrentPreviewOrRC $CurrentPreviewNumberVersion ([ref]$afterDllFolder) VerifyPathOrExit $afterDllFolder - $targetFolder = [IO.Path]::Combine($previewFolderPath, "Microsoft.$adkName.App") + $targetFolder = [IO.Path]::Combine($previewFolderPath, "Microsoft.$sdkName.App") RecreateFolder $targetFolder RunApiDiff2 $apiDiffExe $targetFolder $beforeDllFolder $afterDllFolder $currentDotNetFullName $assembliesToExclude $attributesToExclude $previousDotNetFriendlyName $currentDotNetFriendlyName