From f5a69cfe451d28607cd3ab78299938156abfa99e Mon Sep 17 00:00:00 2001 From: Albert Hui Date: Thu, 20 Aug 2026 04:13:32 +0000 Subject: [PATCH] fix(ci): retry the Dokany MSI download instead of failing on one blip The smoke-windows job went red because `Invoke-WebRequest` died fetching the Dokany MSI. It was not a hang -- the request failed in about 21 seconds -- so the whole Windows smoke run reported a failure over a network blip rather than anything about the code, on a PR that only deleted a dead CI job. Note what is NOT the problem: this job already carries `timeout-minutes: 25`. The six-hour apt hang fixed in fleet-ci was a different failure with a different cause, and the ceiling here was already in place. `-MaximumRetryCount` would not have covered it either: PowerShell retries HTTP 429 and 5xx, not a dropped connection, which is what happened. Hence an explicit loop that catches any terminating error -- three attempts, 15s then 30s backoff, `-TimeoutSec 120` per request, and the partial file removed between attempts so a half-written MSI cannot be picked up by the next one. Exhausting the retries throws with the cause named as the GitHub releases endpoint rather than the code, so the next person reading a red smoke run is not sent looking in the wrong place. Also rejects a truncated download (`< 1MB`). A partial MSI installs as a corrupt one and fails later with a msiexec exit code that says nothing about why. PROVEN ON A REAL RUNNER, not asserted. No arm64 PowerShell image exists, so this could not be exercised locally the way the fleet-ci apt retry was. Instead the negative control ran on windows-latest with the URL pointed at a 404: 04:11:29 attempt 1/3 -> 404 04:11:45 attempt 2/3 -> 404 (15s backoff) 04:12:15 attempt 3/3 -> 404 (30s backoff) 04:12:15 exit 1 Three attempts, the backoff intervals as designed, the real error text surfaced on each, and a fast failure at 46 seconds rather than a pass or a hang. The scratch branch carrying that control has been deleted. --- .github/workflows/mount-smoke.yml | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/.github/workflows/mount-smoke.yml b/.github/workflows/mount-smoke.yml index c128593..cbc54af 100644 --- a/.github/workflows/mount-smoke.yml +++ b/.github/workflows/mount-smoke.yml @@ -79,9 +79,33 @@ jobs: $PSNativeCommandUseErrorActionPreference = $false # Dokany (LGPL/MIT) runtime: kernel driver + System32 dokan2.dll. $msi = "$PWD\Dokan_x64.msi" - Write-Host "Downloading Dokany MSI..." - Invoke-WebRequest https://github.com/dokan-dev/dokany/releases/download/v2.3.0.1000/Dokan_x64.msi -OutFile $msi - Write-Host "Downloaded $((Get-Item $msi).Length) bytes; running msiexec /quiet..." + $url = 'https://github.com/dokan-dev/dokany/releases/download/v2.3.0.1000/Dokan_x64.msi' + # Retried, because this failed the job once on a transient fetch: the + # request died in ~21s and the whole smoke run went red over a network + # blip rather than anything about the code. `-MaximumRetryCount` alone + # would not have helped -- it retries HTTP 429/5xx, not a dropped + # connection -- so the loop catches any terminating error. + $downloaded = $false + foreach ($attempt in 1..3) { + try { + Write-Host "Downloading Dokany MSI (attempt $attempt/3)..." + Invoke-WebRequest $url -OutFile $msi -TimeoutSec 120 + $downloaded = $true + break + } catch { + Write-Host "::warning::Dokany MSI download failed (attempt $attempt/3): $($_.Exception.Message)" + if (Test-Path $msi) { Remove-Item $msi -Force } + if ($attempt -lt 3) { Start-Sleep -Seconds (15 * $attempt) } + } + } + if (-not $downloaded) { + throw "Dokany MSI download failed on all 3 attempts. This is the GitHub releases endpoint being unreachable, not a code failure." + } + # A truncated download installs as a corrupt MSI and fails later with a + # msiexec code that says nothing about the cause, so check it here. + $size = (Get-Item $msi).Length + if ($size -lt 1MB) { throw "Dokany MSI is only $size bytes; the download was truncated." } + Write-Host "Downloaded $size bytes; running msiexec /quiet..." $proc = Start-Process msiexec.exe -ArgumentList '/i',"`"$msi`"",'/quiet','/norestart','/l*v','dokan-install.log' -Wait -PassThru $code = if ($null -ne $proc.ExitCode) { $proc.ExitCode } else { 0 } Write-Host "msiexec exit code: $code"