From e3ad52da239c38e04a98776c1990556cee505007 Mon Sep 17 00:00:00 2001 From: Juho Vainio Date: Wed, 5 Aug 2026 17:40:41 +0000 Subject: [PATCH] fix: retry HTTP download in install.ps1 on transient failure Invoke-WebRequest had no retry logic, so a single transient connection failure (e.g. connection reset, or the server-side listener not yet ready) would abort the install outright. This is the exact failure signature behind the intermittent lifecycle-windows-http-install E2E flake, and it also affects real production HTTP downloads. The expectations.toml flaky mechanism was considered but doesn't fit here: it only tolerates an unexpected pass of a known-bug xfail scenario, not an unexpected fail of an expect-pass scenario, so it can't be reused to tolerate this failure mode without a design change to the expectation system itself. Save-File now retries the Invoke-WebRequest call up to 3 times with a short increasing backoff before failing. The local file:// (Copy-Item) path is untouched since it isn't networked and isn't implicated in the flake. Signed-off-by: Juho Vainio --- install.ps1 | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/install.ps1 b/install.ps1 index 966f6456..a83f057e 100644 --- a/install.ps1 +++ b/install.ps1 @@ -163,11 +163,22 @@ function Save-File { if ($PSVersionTable.PSVersion.Major -lt 6) { $parameters.UseBasicParsing = $true } - try { - Invoke-WebRequest @parameters - } catch { - Remove-Item -LiteralPath $OutputPath -Force -ErrorAction SilentlyContinue - Fail "${FailureMessage}: $($_.Exception.Message)" + + # An HTTP transfer can fail transiently (a momentary connection reset, or + # the server-side listener still finishing setup) even though a retry a + # moment later succeeds; give it a couple of chances before giving up. + $maxAttempts = 3 + for ($attempt = 1; $attempt -le $maxAttempts; $attempt++) { + try { + Invoke-WebRequest @parameters + return + } catch { + Remove-Item -LiteralPath $OutputPath -Force -ErrorAction SilentlyContinue + if ($attempt -eq $maxAttempts) { + Fail "${FailureMessage}: $($_.Exception.Message)" + } + Start-Sleep -Milliseconds (250 * $attempt) + } } }