Files
opensquilla--opensquilla/.github/scripts/verify-release-windows-upgrade.ps1
2026-07-13 13:12:33 +08:00

127 lines
5.2 KiB
PowerShell

param(
[Parameter(Mandatory = $true)]
[string]$CandidateInstaller,
[Parameter(Mandatory = $true)]
[ValidatePattern('^[A-Za-z0-9._-]{1,80}$')]
[string]$Label
)
$ErrorActionPreference = 'Stop'
$repository = 'opensquilla/opensquilla'
$oldTag = 'v0.5.0rc3'
$oldAsset = 'OpenSquilla-0.5.0-rc3-win-x64.exe'
$candidate = (Resolve-Path -LiteralPath $CandidateInstaller).Path
$sandbox = Join-Path $env:RUNNER_TEMP "opensquilla-release-preservation-$Label"
$oldDir = Join-Path $sandbox 'rc3'
$installDir = Join-Path $sandbox 'OpenSquilla'
$appData = Join-Path $sandbox 'appdata'
$userData = Join-Path $appData 'OpenSquilla'
$profile = Join-Path $userData 'opensquilla'
$probe = Join-Path $PWD '.github\scripts\verify-release-profile-preservation.py'
$env:APPDATA = $appData
$env:OPENSQUILLA_DESKTOP_DISABLE_AUTO_UPDATE = '1'
$env:OPENSQUILLA_RECOVERY_OFFLINE = '1'
New-Item -ItemType Directory -Force -Path $oldDir, $appData | Out-Null
gh release download $oldTag --repo $repository --pattern $oldAsset --dir $oldDir
if ($LASTEXITCODE -ne 0) { throw 'Failed to download the RC3 Windows installer.' }
$oldInstaller = Join-Path $oldDir $oldAsset
function Stop-InstalledProcesses {
Get-Process -Name 'OpenSquilla', 'opensquilla-gateway' -ErrorAction SilentlyContinue |
ForEach-Object {
try {
$path = if ($_.Path) { [IO.Path]::GetFullPath($_.Path) } else { '' }
$prefix = [IO.Path]::GetFullPath($installDir + [IO.Path]::DirectorySeparatorChar)
if ($path.StartsWith($prefix, [StringComparison]::OrdinalIgnoreCase)) {
& taskkill.exe /PID $_.Id /T /F 2>$null | Out-Null
}
} catch {
if ($_.Exception.Message -notmatch 'exited|cannot find|No process') { throw }
}
}
}
try {
$old = Start-Process -FilePath $oldInstaller -ArgumentList @('/S', "/D=$installDir") `
-Wait -PassThru
if ($old.ExitCode -ne 0) { throw "RC3 installer failed with exit code $($old.ExitCode)." }
python $probe seed --home $profile --label $Label
if ($LASTEXITCODE -ne 0) { throw 'Failed to seed the synthetic RC3 profile.' }
$installed = Start-Process -FilePath $candidate -ArgumentList @('/S', "/D=$installDir") `
-Wait -PassThru
if ($installed.ExitCode -ne 0) {
throw "Candidate installer failed with exit code $($installed.ExitCode)."
}
python $probe verify --home $profile --label $Label
if ($LASTEXITCODE -ne 0) { throw 'Candidate installation changed RC3 profile data.' }
$app = Join-Path $installDir 'OpenSquilla.exe'
if (-not (Test-Path -LiteralPath $app -PathType Leaf)) {
throw 'Candidate installation did not publish OpenSquilla.exe.'
}
$launched = Start-Process -FilePath $app `
-ArgumentList @('--use-mock-keychain', "--user-data-dir=$userData") -PassThru
Start-Sleep -Seconds 8
if ($launched.HasExited) {
throw "Candidate Desktop exited during launch verification: $($launched.ExitCode)"
}
Stop-InstalledProcesses
$gateway = Get-ChildItem -Path (Join-Path $installDir 'resources\runtime\gateway') `
-Filter 'opensquilla-gateway.exe' -File -Recurse | Select-Object -First 1
if (-not $gateway) { throw 'Packaged recovery CLI was not found.' }
$inspectionRaw = & $gateway.FullName recovery inspect --home $profile --json
if ($LASTEXITCODE -ne 0) { throw 'Packaged recovery inspection failed.' }
$inspection = $inspectionRaw | ConvertFrom-Json
if ($inspection.outcome -notin @('ready', 'attention')) {
throw "Unsafe packaged profile inspection: $inspectionRaw"
}
if ([IO.Path]::GetFullPath($inspection.primary_home) -ne [IO.Path]::GetFullPath($profile)) {
throw 'Candidate selected a different primary profile after upgrade.'
}
if (
[IO.Path]::GetFullPath($inspection.effective_workspace) -ne
[IO.Path]::GetFullPath((Join-Path $profile 'workspace'))
) {
throw 'Candidate selected a different workspace after upgrade.'
}
$configuredState = @($inspection.candidates | Where-Object {
$_.kind -eq 'state' -and $_.configured -and $_.valid
})
if (
$configuredState.Count -ne 1 -or
[IO.Path]::GetFullPath($configuredState[0].path) -ne
[IO.Path]::GetFullPath((Join-Path $profile 'state'))
) {
throw 'Candidate selected a different state directory after upgrade.'
}
python $probe verify --home $profile --label $Label
if ($LASTEXITCODE -ne 0) { throw 'Candidate launch changed RC3 profile data.' }
$uninstaller = Get-ChildItem -LiteralPath $installDir -Filter 'Uninstall*.exe' -File |
Select-Object -First 1
if (-not $uninstaller) { throw 'Candidate Windows uninstaller was not found.' }
$uninstall = Start-Process -FilePath $uninstaller.FullName -ArgumentList @('/S') `
-Wait -PassThru
if ($uninstall.ExitCode -ne 0) {
throw "Candidate uninstaller failed with exit code $($uninstall.ExitCode)."
}
$deadline = [DateTime]::UtcNow.AddSeconds(30)
while (
(Test-Path -LiteralPath $app -PathType Leaf) -and
[DateTime]::UtcNow -lt $deadline
) {
Start-Sleep -Seconds 1
}
if (Test-Path -LiteralPath $app -PathType Leaf) {
throw 'Candidate uninstaller did not remove OpenSquilla.exe.'
}
python $probe verify --home $profile --label $Label
if ($LASTEXITCODE -ne 0) { throw 'Candidate uninstaller changed RC3 profile data.' }
} finally {
Stop-InstalledProcesses
}