fix(release): retry uploads with backoff + drop Gitea workflows

Gitea/nginx intermittently returns 504 on large multipart uploads even
when curl successfully streamed the body. Add up to 4 retries with
exponential backoff (15s/45s/2m/5m). Before each retry, check whether
the asset is actually present server-side at the expected size — Gitea
sometimes accepts the body but times out the response, so the file is
already there.

Also drop .gitea/workflows/* — we use release.ps1 locally and Gitea
Actions runners are not configured, so every push was leaving queued/
failed workflow runs in the Actions tab.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
AnRil
2026-05-18 21:51:41 +07:00
parent 3f038e59e8
commit 6160ece8d4
3 changed files with 56 additions and 151 deletions

View File

@@ -157,21 +157,66 @@ if ($curlCmd) {
}
}
$maxRetries = 4
$backoffs = @(15, 45, 120, 300) # seconds between attempts
foreach ($asset in @($installer, $blockmap, $manifest)) {
$name = Split-Path $asset -Leaf
$size = (Get-Item $asset).Length
Write-Host ("Uploading {0} ({1:N1} MB)..." -f $name, ($size / 1MB)) -ForegroundColor Cyan
$uri = "$apiBase/repos/$repoOwner/$repoName/releases/$($release.id)/assets?name=$([uri]::EscapeDataString($name))"
# -f: fail on HTTP errors; -s -S: silent but show errors; --data-binary @file
& $curl `
--fail-with-body `
--silent --show-error `
-H "Authorization: token $env:GITEA_TOKEN" `
-H "Content-Type: application/octet-stream" `
--data-binary "@$asset" `
$uri
if ($LASTEXITCODE -ne 0) {
Write-Error "Upload failed for $name (curl exit $LASTEXITCODE)"
$attempt = 0
$uploaded = $false
while (-not $uploaded -and $attempt -le $maxRetries) {
if ($attempt -gt 0) {
$wait = $backoffs[[Math]::Min($attempt - 1, $backoffs.Length - 1)]
Write-Host (" Retrying in {0}s (attempt {1}/{2})..." -f $wait, ($attempt + 1), ($maxRetries + 1)) -ForegroundColor Yellow
Start-Sleep -Seconds $wait
# Re-check whether prior attempt actually succeeded server-side before
# 504-ing the client. If asset is already there, treat as success.
try {
$check = Invoke-RestMethod `
-Uri "$apiBase/repos/$repoOwner/$repoName/releases/$($release.id)/assets" `
-Method Get -Headers $headers
$existing = $check | Where-Object { $_.name -eq $name }
if ($existing -and $existing.size -eq $size) {
Write-Host " Asset already present server-side ($($existing.size) bytes) — skipping retry." -ForegroundColor DarkGray
$uploaded = $true
break
}
# If asset is present but with wrong size (half-uploaded), delete first.
if ($existing) {
Write-Host " Removing partial asset id=$($existing.id) ($($existing.size) bytes) before retry..." -ForegroundColor DarkGray
Invoke-RestMethod `
-Uri "$apiBase/repos/$repoOwner/$repoName/releases/$($release.id)/assets/$($existing.id)" `
-Method Delete -Headers $headers | Out-Null
}
} catch {
# If the list call itself fails, just proceed with the retry.
}
}
Write-Host ("Uploading {0} ({1:N1} MB)..." -f $name, ($size / 1MB)) -ForegroundColor Cyan
& $curl `
--fail-with-body `
--silent --show-error `
--connect-timeout 30 `
--max-time 900 `
-H "Authorization: token $env:GITEA_TOKEN" `
-H "Content-Type: application/octet-stream" `
--data-binary "@$asset" `
$uri
if ($LASTEXITCODE -eq 0) {
$uploaded = $true
} else {
Write-Host " curl exit $LASTEXITCODE — will retry." -ForegroundColor Yellow
$attempt++
}
}
if (-not $uploaded) {
Write-Error "Upload failed for $name after $($maxRetries + 1) attempts."
exit 1
}
}