diff --git a/packages/http-client-csharp/eng/scripts/Update-PackageJson.ps1 b/packages/http-client-csharp/eng/scripts/Update-PackageJson.ps1 index 0c3211f5fbd..51b800093f7 100644 --- a/packages/http-client-csharp/eng/scripts/Update-PackageJson.ps1 +++ b/packages/http-client-csharp/eng/scripts/Update-PackageJson.ps1 @@ -93,6 +93,72 @@ function Get-LatestGAVersion { } } +# Function to check if a dependency version's peer dep on tcgc is satisfied by our tcgcVersion +function Test-TcgcCompatibility { + param( + [string]$PackageName, + [string]$PackageVersion, + [string]$TcgcVersion + ) + + Write-Host "Checking if $PackageName@$PackageVersion is compatible with tcgc@$TcgcVersion..." + $tcgcRange = & npm view "${PackageName}@${PackageVersion}" "peerDependencies.@azure-tools/typespec-client-generator-core" 2>&1 + + if ($LASTEXITCODE -ne 0 -or -not $tcgcRange) { + Write-Host " No tcgc peer dependency found, assuming compatible" + return $true + } + + $tcgcRange = ($tcgcRange | Out-String).Trim() + Write-Host " Requires tcgc: $tcgcRange" + + $jsCode = "try{console.log(require('semver').satisfies('$TcgcVersion','$tcgcRange'))}catch(e){console.log('error')}" + $semverResult = (& node -e $jsCode 2>&1 | Out-String).Trim() + + if ($semverResult -eq 'true') { + Write-Host " ✓ Compatible" + return $true + } else { + Write-Host " ✗ Not compatible" + return $false + } +} + +# Function to get previous GA versions of a package sorted descending, before a given version +function Get-PreviousGAVersions { + param( + [string]$PackageName, + [string]$BeforeVersion + ) + + Write-Host "Getting previous GA versions of $PackageName (before $BeforeVersion)..." + $result = & npm view $PackageName versions --json 2>&1 + + if ($LASTEXITCODE -ne 0) { + Write-Warning "Could not retrieve versions for $PackageName" + return @() + } + + $allVersions = ($result | Out-String) | ConvertFrom-Json + + if ($allVersions -isnot [array]) { + $allVersions = @($allVersions) + } + + # Filter to GA only (no prerelease) and versions strictly less than BeforeVersion + $gaVersions = @($allVersions | Where-Object { + $_ -notmatch '-' -and ([version]$_ -lt [version]$BeforeVersion) + } | Sort-Object { [version]$_ } -Descending) + + if ($gaVersions.Count -gt 0) { + Write-Host " Found $($gaVersions.Count) previous GA version(s), most recent: $($gaVersions[0])" + } else { + Write-Host " No previous GA versions found" + } + + return $gaVersions +} + # Resolve paths $PackageJsonPath = Resolve-Path $PackageJsonPath @@ -140,29 +206,53 @@ try { $dependencyVersions = @{} foreach ($dependency in $InjectedDependencies) { - $versionToUse = $tcgcVersion + $versionToUse = $null - # Check if the tcgc version exists for this dependency - if (-not (Test-PackageVersion -PackageName $dependency -Version $tcgcVersion)) { - Write-Warning "Version $tcgcVersion not found for $dependency" - - # Use the version from tcgc's @azure-tools/typespec-azure-core dependency as fallback - if ($fallbackVersion -and (Test-PackageVersion -PackageName $dependency -Version $fallbackVersion)) { + # 1. Try the tcgc version if it exists and is compatible with our tcgc + if ((Test-PackageVersion -PackageName $dependency -Version $tcgcVersion) -and + (Test-TcgcCompatibility -PackageName $dependency -PackageVersion $tcgcVersion -TcgcVersion $tcgcVersion)) { + $versionToUse = $tcgcVersion + } + + # 2. Search up to 2 previous GA versions for one compatible with our tcgc + if (-not $versionToUse) { + Write-Host "Searching previous GA versions of $dependency compatible with tcgc@$tcgcVersion..." + $previousVersions = Get-PreviousGAVersions -PackageName $dependency -BeforeVersion $tcgcVersion + $attempts = 0 + foreach ($prevVersion in $previousVersions) { + if ($attempts -ge 2) { break } + $attempts++ + + if (Test-TcgcCompatibility -PackageName $dependency -PackageVersion $prevVersion -TcgcVersion $tcgcVersion) { + $versionToUse = $prevVersion + Write-Host "Found compatible previous version: $dependency@$prevVersion" + break + } + } + } + + # 3. Fallback: use the version from tcgc's azure-core dependency + if (-not $versionToUse -and $fallbackVersion) { + if (Test-PackageVersion -PackageName $dependency -Version $fallbackVersion) { Write-Host "Using fallback version $fallbackVersion for $dependency" $versionToUse = $fallbackVersion - } else { - # Final fallback: use the latest GA version of the package - $latestGA = Get-LatestGAVersion -PackageName $dependency - if ($latestGA) { - Write-Host "Using latest GA version $latestGA for $dependency" - $versionToUse = $latestGA - } else { - Write-Error "Could not determine a valid version for $dependency (no fallback available)" - exit 1 - } } } + # 4. Final fallback: latest GA version + if (-not $versionToUse) { + $latestGA = Get-LatestGAVersion -PackageName $dependency + if ($latestGA) { + Write-Host "Using latest GA version $latestGA for $dependency" + $versionToUse = $latestGA + } + } + + if (-not $versionToUse) { + Write-Error "Could not determine a valid version for $dependency (no fallback available)" + exit 1 + } + # Store the version to use for this dependency $dependencyVersions[$dependency] = $versionToUse