openai/openai-dotnet

Public

mirrored from https://github.com/openai/openai-dotnetAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
joseharriaga/stable-api-listing

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

scripts/Test-ApiCompatibility.ps1

203lines · modecode

1<#
2.SYNOPSIS
3 Validates API compatibility between different versions of a .NET NuGet package.
4
5.DESCRIPTION
6 This script performs API compatibility checks between a current version of a .NET package
7 and a specified baseline version from NuGet.org. It uses the 'apicompat' tool to detect
8 breaking changes and supports excluding specific namespaces from the comparison.
9
10 The script performs these operations in sequence:
11 1. Builds and packs the current version of the package
12 2. Downloads the specified baseline version from NuGet.org
13 3. Compares the two versions using the 'apicompat' tool
14 4. Reports any breaking changes found in non-ignored namespaces
15
16.PARAMETER ProjectPath
17 The path to the .NET project file (.csproj) to build and analyze
18
19.PARAMETER ReleasePath
20 The output directory where the built package will be placed
21
22.PARAMETER PackageName
23 The name of the NuGet package to compare
24
25.PARAMETER BaselineVersion
26 The version number of the baseline package to compare against
27
28.PARAMETER IgnoredNamespaces
29 An optional array of namespace names to exclude from the compatibility check
30
31.EXAMPLE
32 .\Test-ApiCompatibility.ps1
33 Runs the compatibility check using default parameters for the OpenAI SDK
34
35.EXAMPLE
36 Invoke-APICompat -ProjectPath "src\MyProject.csproj" -ReleasePath "src\bin\Release" -PackageName "MyPackage" -BaselineVersion "1.0.0"
37 Runs a compatibility check between the current version and version 1.0.0 of MyPackage
38
39.NOTES
40 The script will generate warnings if breaking changes are detected in non-ignored namespaces.
41#>
42
43function Invoke-DotNetBuild {
44 param(
45 [Parameter(Mandatory = $true)]
46 [string]$ProjectPath
47 )
48
49 Write-Output "Building $($ProjectPath)..."
50 Write-Output ""
51 & dotnet build $ProjectPath
52 Write-Output ""
53}
54
55function Invoke-DotNetPack {
56 param(
57 [Parameter(Mandatory = $true)]
58 [string]$ProjectPath
59 )
60
61 Write-Output "Packing $($ProjectPath)..."
62 Write-Output ""
63 & dotnet pack $ProjectPath
64 Write-Output ""
65}
66
67function Invoke-APICompat {
68 param (
69 [Parameter(Mandatory = $true)]
70 [string]$ProjectPath,
71
72 [Parameter(Mandatory = $true)]
73 [string]$DirectoryBuildPropsPath,
74
75 [Parameter(Mandatory = $true)]
76 [string]$ReleasePath,
77
78 [Parameter(Mandatory = $true)]
79 [string]$PackageName,
80
81 [Parameter(Mandatory = $true)]
82 [string]$BaselineVersion,
83
84 [Parameter(Mandatory = $false)]
85 [string[]]$IgnoredNamespaces
86 )
87
88 try
89 {
90 Invoke-DotNetBuild -ProjectPath $ProjectPath
91
92 Invoke-DotNetPack -ProjectPath $ProjectPath
93
94 # Extract the values of VersionPrefix and VersionSuffix from the .csproj XML file.
95 $xml = [xml](Get-Content $DirectoryBuildPropsPath)
96 $versionPropertyGroup = $xml.Project.PropertyGroup | Where-Object { $_.VersionPrefix -or $_.VersionSuffix } | Select-Object -First 1
97
98 if (-not $versionPropertyGroup) {
99 throw "Could not find version information in '$DirectoryBuildPropsPath'."
100 }
101
102 $versionPrefix = $versionPropertyGroup.VersionPrefix
103 $versionSuffix = $versionPropertyGroup.VersionSuffix
104 $currentVersion = [string]::IsNullOrEmpty($versionSuffix) ? "$($versionPrefix)" : "$($versionPrefix)-$($versionSuffix)"
105
106 $currentNuGetPackagePath = Join-Path $ReleasePath "$($PackageName).$($currentVersion).nupkg"
107 $currentNuGetSymbolsPath = Join-Path $ReleasePath "$($PackageName).$($currentVersion).snupkg"
108
109 # Create temporary folder
110 $tempFolderPath = Join-Path $PSScriptRoot "TempApiCompatibility"
111 New-Item -ItemType Directory -Path $tempFolderPath -Force | Out-Null
112
113 # Download OpenAI NuGet package
114 $baselineNuGetPackageName = "$($PackageName).$($BaselineVersion).nupkg"
115 $baselineNuGetPackagePath = Join-Path $tempFolderPath $baselineNuGetPackageName
116 $baselineNuGetPackageUrl = "https://www.nuget.org/api/v2/package/$($PackageName)/$($BaselineVersion)"
117 Invoke-RestMethod -Uri $baselineNuGetPackageUrl -OutFile $baselineNuGetPackagePath
118 Sleep 10
119
120 Write-Output "Testing API compatibility between versions $($currentVersion) (current) and $($BaselineVersion) (baseline)..."
121 Write-Output ""
122
123 # Run apicompat and redirect the error output to a variable
124 $output = apicompat package $currentNuGetPackagePath --baseline-package $baselineNuGetPackagePath 2>&1
125
126 # Individual warnings from apicompat have identifiers such as "CP0001", "CP0002", etc.
127 $warningRegex = "CP\d\d\d\d"
128
129 # Concatenate the ignored namespaces into a single string, delimiting them by "|" and escaping the "."
130 $ignoredRegex = if ($IgnoredNamespaces) {
131 ($IgnoredNamespaces | ForEach-Object { [regex]::Escape($_) }) -join "|"
132 }
133
134 $warningsFound = 0
135
136 foreach ($line in $($output -split "`r`n")) {
137 if ($line -cmatch $warningRegex) {
138 if (-not $ignoredRegex -or $line -cnotmatch $ignoredRegex) {
139 $warningsFound++
140 }
141 }
142 }
143
144 if ($warningsFound -eq 0) {
145 Write-Output "No API breaking changes found."
146 Write-Output ""
147 }
148 else {
149 foreach ($line in $($output -split "`r`n")) {
150 if ($line -cmatch $warningRegex) {
151 if (-not $ignoredRegex -or $line -cnotmatch $ignoredRegex){
152 Write-Warning "$line"
153 Write-Output ""
154 }
155 }
156 else {
157 Write-Output "$line"
158 Write-Output ""
159 }
160 }
161 }
162 }
163 finally {
164 if ($tempFolderPath -and (Test-Path $tempFolderPath)) {
165 Remove-Item -Path $tempFolderPath -Recurse -Force
166 }
167
168 if ($currentNuGetPackagePath -and (Test-Path $currentNuGetPackagePath)) {
169 Remove-Item -Path $currentNuGetPackagePath -Force
170 }
171
172 if ($currentNuGetSymbolsPath -and (Test-Path $currentNuGetSymbolsPath)) {
173 Remove-Item -Path $currentNuGetSymbolsPath -Force
174 }
175 }
176}
177
178$repoRootPath = Join-Path $PSScriptRoot .. -Resolve
179$projectPath = Join-Path $repoRootPath "src\OpenAI.csproj"
180$buildPropsPath = Join-Path $repoRootPath "Directory.Build.props"
181$releasePath = Join-Path $repoRootPath "src\bin\Release"
182
183$experimentalNamespaces = @(
184 "OpenAI.Assistants",
185 "OpenAI.Batch",
186 "OpenAI.Containers",
187 "OpenAI.Conversations",
188 "OpenAI.Evals",
189 "OpenAI.FineTuning",
190 "OpenAI.Graders",
191 "OpenAI.Realtime",
192 "OpenAI.Responses",
193 "OpenAI.Skills",
194 "OpenAI.VectorStores",
195 "OpenAI.Videos"
196)
197
198Invoke-APICompat -ProjectPath $projectPath `
199 -DirectoryBuildPropsPath $buildPropsPath `
200 -ReleasePath $releasePath `
201 -PackageName "OpenAI" `
202 -BaselineVersion "2.9.1" `
203 -IgnoredNamespaces $experimentalNamespaces
204