Browse Source

Implement rate limiting in NuGet package push script to manage push frequency and enhance error handling for 4xx responses by parsing retry-after values.

pull/25388/head
selmankoc 3 weeks ago
parent
commit
b42210683f
  1. 39
      nupkg/push_packages.ps1

39
nupkg/push_packages.ps1

@ -13,7 +13,9 @@ $failedPackages = @()
$totalProjectsCount = $projects.length
$nugetUrl = "https://api.nuget.org/v3/index.json"
$maxQuotaRetryCount = 3
$quotaRetryDelaysInSeconds = @(30, 60, 120)
$defaultQuotaRetryDelaysInSeconds = @(30, 60, 120)
$maxPushesPerHour = 250 # NuGet.org rate limit (conservative). Set 0 to disable.
$pushTimestamps = [System.Collections.Generic.List[datetime]]::new()
$failedPackagesFilePath = Join-Path $packFolder "failed-packages.txt"
Set-Location $packFolder
if (Test-Path $failedPackagesFilePath) { Remove-Item $failedPackagesFilePath -Force }
@ -29,6 +31,25 @@ foreach($project in $projects) {
if ($nugetPackageExists)
{
# Sliding-window rate limiter: ensure we don't exceed $maxPushesPerHour pushes per hour
if ($maxPushesPerHour -gt 0)
{
$windowStart = (Get-Date).AddHours(-1)
$recentPushes = $pushTimestamps | Where-Object { $_ -gt $windowStart }
$pushTimestamps = [System.Collections.Generic.List[datetime]]$recentPushes
if ($pushTimestamps.Count -ge $maxPushesPerHour)
{
$waitUntil = $pushTimestamps[0].AddHours(1)
$waitSeconds = [int]([math]::Ceiling(($waitUntil - (Get-Date)).TotalSeconds)) + 1
if ($waitSeconds -gt 0)
{
Write-Warning "Rate limit: $($pushTimestamps.Count) pushes in the last hour (limit: $maxPushesPerHour). Pausing $waitSeconds seconds until the window resets..."
Start-Sleep -Seconds $waitSeconds
}
}
}
$attempt = 0
$pushSucceeded = $false
while ($true)
@ -51,7 +72,17 @@ foreach($project in $projects) {
break
}
$retryDelay = $quotaRetryDelaysInSeconds[$attempt - 1]
# Parse the retry-after value from the NuGet response if present (e.g. "retry after: 2974s")
$retryAfterMatch = ($pushOutput | Out-String) | Select-String -Pattern 'retry after:\s*(\d+)s' -AllMatches
if ($retryAfterMatch -and $retryAfterMatch.Matches.Count -gt 0)
{
$retryDelay = [int]$retryAfterMatch.Matches[0].Groups[1].Value
}
else
{
$retryDelay = $defaultQuotaRetryDelaysInSeconds[$attempt - 1]
}
Write-Warning "NuGet push returned a 4xx response for $nugetPackageName. Retrying in $retryDelay seconds (retry $attempt/$maxQuotaRetryCount)..."
Start-Sleep -Seconds $retryDelay
}
@ -62,6 +93,10 @@ foreach($project in $projects) {
$errorCount += 1
$failedPackages += $nugetPackageName
}
else
{
$pushTimestamps.Add((Get-Date))
}
#Write-Host ("Deleting package from local: " + $nugetPackageName)
#Remove-Item $nugetPackageName -Force
}

Loading…
Cancel
Save