From d5be1f824a25e9154a6af79b99a3bdc025bbc0e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E9=98=BF=E6=B1=9F=28Relakkes?= =?UTF-8?q?=29?= Date: Tue, 14 Jul 2026 04:18:58 +0800 Subject: [PATCH] fix(release): bound Windows installer smoke waits --- desktop/scripts/windows-installer-smoke.ps1 | 28 +++++++++++++++------ scripts/pr/release-workflow.test.ts | 6 ++++- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/desktop/scripts/windows-installer-smoke.ps1 b/desktop/scripts/windows-installer-smoke.ps1 index 8fa50794..d456d44e 100644 --- a/desktop/scripts/windows-installer-smoke.ps1 +++ b/desktop/scripts/windows-installer-smoke.ps1 @@ -32,15 +32,27 @@ foreach ($name in @('APPDATA', 'LOCALAPPDATA', 'USERPROFILE', 'CLAUDE_CONFIG_DIR $savedEnvironment[$name] = [Environment]::GetEnvironmentVariable($name, 'Process') } -function Invoke-CheckedInstaller { +function Invoke-CheckedProcess { param( + [Parameter(Mandatory = $true)][string]$FilePath, [Parameter(Mandatory = $true)][string]$Stage, - [Parameter(Mandatory = $true)][string[]]$Arguments + [Parameter(Mandatory = $true)][string[]]$Arguments, + [int]$TimeoutSeconds = 180 ) - $process = Start-Process -FilePath $installer -ArgumentList $Arguments -Wait -PassThru - if ($process.ExitCode -ne 0) { - throw "$Stage failed with installer exit code $($process.ExitCode)." + [Console]::Out.WriteLine("$Stage starting...") + $process = Start-Process -FilePath $FilePath -ArgumentList $Arguments -PassThru + try { + if (-not $process.WaitForExit($TimeoutSeconds * 1000)) { + Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue + throw "$Stage timed out after $TimeoutSeconds seconds." + } + if ($process.ExitCode -ne 0) { + throw "$Stage failed with process exit code $($process.ExitCode)." + } + [Console]::Out.WriteLine("$Stage completed successfully.") + } finally { + $process.Dispose() } } @@ -52,12 +64,12 @@ try { Remove-Item Env:CLAUDE_CONFIG_DIR -ErrorAction SilentlyContinue Remove-Item Env:CC_HAHA_APP_PORTABLE_DIR -ErrorAction SilentlyContinue - Invoke-CheckedInstaller -Stage 'Fresh install' -Arguments @('/S', '/currentuser', "/D=$installDir") + Invoke-CheckedProcess -FilePath $installer -Stage 'Fresh install' -Arguments @('/S', '/currentuser', "/D=$installDir") if (-not (Test-Path -LiteralPath $appExe -PathType Leaf)) { throw "Fresh install did not create the application executable: $appExe" } - Invoke-CheckedInstaller -Stage 'Default-mode reinstall' -Arguments @('--updated', '/S', '/currentuser', "/D=$installDir") + Invoke-CheckedProcess -FilePath $installer -Stage 'Default-mode reinstall' -Arguments @('--updated', '/S', '/currentuser', "/D=$installDir") if (-not (Test-Path -LiteralPath $appExe -PathType Leaf)) { throw "Reinstall removed the application executable: $appExe" } @@ -65,7 +77,7 @@ try { [Console]::Out.WriteLine('Windows installer fresh-install and default-mode reinstall smoke passed.') } finally { if (Test-Path -LiteralPath $uninstaller -PathType Leaf) { - Start-Process -FilePath $uninstaller -ArgumentList @('/S', '/KEEP_APP_DATA', '/currentuser') -Wait | Out-Null + Invoke-CheckedProcess -FilePath $uninstaller -Stage 'Cleanup uninstall' -Arguments @('/S', '/KEEP_APP_DATA', '/currentuser') -TimeoutSeconds 120 } foreach ($name in $savedEnvironment.Keys) { $value = $savedEnvironment[$name] diff --git a/scripts/pr/release-workflow.test.ts b/scripts/pr/release-workflow.test.ts index 5a11cb03..083a68c3 100644 --- a/scripts/pr/release-workflow.test.ts +++ b/scripts/pr/release-workflow.test.ts @@ -549,9 +549,13 @@ describe('release desktop workflow', () => { expect(workflow).toContain('windows-installer-smoke.ps1') } - expect(installerSmoke).toContain('Invoke-CheckedInstaller') + expect(installerSmoke).toContain('Invoke-CheckedProcess') expect(installerSmoke).toContain("@('/S', '/currentuser'") expect(installerSmoke).toContain("@('--updated', '/S', '/currentuser'") + expect(installerSmoke).toContain('$process.WaitForExit($TimeoutSeconds * 1000)') + expect(installerSmoke).not.toContain('-Wait -PassThru') + expect(installerSmoke).toContain('$Stage starting...') + expect(installerSmoke).toContain('$Stage completed successfully.') expect(installerSmoke).toContain('Fresh install did not create the application executable') expect(installerSmoke).toContain('Reinstall removed the application executable') })