ci-platforms / darwin arm64 smoke (push) Skipped
ci / build (amd64, linux, ubuntu-24.04) (push) Failing after 12m19s
ci-platforms / darwin amd64 smoke (push) Skipped
ci-platforms / windows amd64 smoke (push) Skipped
github-native / gitea-pending (push) Skipped
github-native / darwin amd64 native (push) Skipped
github-native / linux amd64 native (push) Skipped
github-native / windows amd64 native (push) Skipped
github-native / darwin arm64 native (push) Skipped
github-native / gitea-result (push) Skipped
ci / checks (push) Failing after 23m57s
ci / release (push) Skipped
GitHub / windows amd64 native GitHub-hosted native CI: failure
GitHub / darwin arm64 native GitHub-hosted native CI: failure
GitHub / darwin amd64 native GitHub-hosted native CI: failure
GitHub / linux amd64 native GitHub-hosted native CI: success
128 lines
8.3 KiB
PowerShell
128 lines
8.3 KiB
PowerShell
$ErrorActionPreference = 'Stop'
|
|
|
|
# The installer kills processes by executable name and changes HKCU. Never run
|
|
# it on a developer machine or a self-hosted runner.
|
|
if ($env:GITHUB_ACTIONS -ne 'true' -or $env:RUNNER_ENVIRONMENT -ne 'github-hosted' -or
|
|
$env:GITHUB_SERVER_URL -ne 'https://github.com') {
|
|
throw 'Installer smoke is restricted to an ephemeral GitHub-hosted runner.'
|
|
}
|
|
if (Get-Process aego-editor -ErrorAction SilentlyContinue) { throw 'An editor is already running.' }
|
|
$install = Join-Path $env:RUNNER_TEMP 'aego-ci-install'
|
|
if ($install.Contains(' ')) { throw 'NSIS /D requires an unquoted install path; runner temp contains spaces.' }
|
|
$registry = @(
|
|
'HKCU:\Software\Aego',
|
|
'HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\Aego',
|
|
'HKCU:\Software\Classes\Aego.Project',
|
|
'HKCU:\Software\Classes\Aego.Scene',
|
|
'HKCU:\Software\Classes\Aego.Prefab',
|
|
'HKCU:\Software\Classes\Directory\shell\Aego',
|
|
'HKCU:\Software\Classes\Directory\Background\shell\Aego',
|
|
'HKCU:\Software\Classes\.aego',
|
|
'HKCU:\Software\Classes\.aescene',
|
|
'HKCU:\Software\Classes\.aeprefab'
|
|
)
|
|
foreach ($key in $registry) { if (Test-Path $key) { throw "Refusing to overwrite existing key: $key" } }
|
|
$startMenu = Join-Path ([Environment]::GetFolderPath('Programs')) 'Aego'
|
|
$desktop = Join-Path ([Environment]::GetFolderPath('Desktop')) 'Aego.lnk'
|
|
if ((Test-Path $install) -or (Test-Path $startMenu) -or (Test-Path $desktop)) {
|
|
throw 'Install directory or shortcuts already exist.'
|
|
}
|
|
$beforePath = [Environment]::GetEnvironmentVariable('Path', 'User')
|
|
$envKey = [Microsoft.Win32.Registry]::CurrentUser.CreateSubKey('Environment', $true)
|
|
$rawPresent = @($envKey.GetValueNames()) -icontains 'Path'
|
|
$rawBefore = if ($rawPresent) { [string]$envKey.GetValue('Path', '', [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames) } else { '' }
|
|
$rawKind = if ($rawPresent) { $envKey.GetValueKind('Path') } else { [Microsoft.Win32.RegistryValueKind]::ExpandString }
|
|
$pathScript = Join-Path $env:GITHUB_WORKSPACE 'tools\release\windows\path.ps1'
|
|
$testDir = Join-Path $env:RUNNER_TEMP "aego-path-test's"
|
|
try {
|
|
# The runner is ephemeral. Exercise the actual registry adapter before the
|
|
# installer, including empty segments, external edits and an existing entry.
|
|
$fixture = 'C:\Tools;;%LOCALAPPDATA%\Example;'
|
|
$envKey.SetValue('Path', $fixture, [Microsoft.Win32.RegistryValueKind]::ExpandString)
|
|
& $pathScript -Action Install -Directory $testDir
|
|
$added = [string]$envKey.GetValue('Path', '', [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames)
|
|
if ($added -cne "$fixture;$testDir") { throw 'PATH installation changed existing segments.' }
|
|
$envKey.SetValue('Path', "$added;C:\AddedLater;;", [Microsoft.Win32.RegistryValueKind]::ExpandString)
|
|
& $pathScript -Action Uninstall -Directory $testDir
|
|
$after = [string]$envKey.GetValue('Path', '', [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames)
|
|
if ($after -cne "$fixture;C:\AddedLater;;" -or $envKey.GetValueKind('Path') -ne [Microsoft.Win32.RegistryValueKind]::ExpandString) {
|
|
throw 'PATH uninstall changed unrelated entries or its registry type.'
|
|
}
|
|
$preexisting = "C:\Tools;$testDir;"
|
|
$envKey.SetValue('Path', $preexisting, [Microsoft.Win32.RegistryValueKind]::String)
|
|
& $pathScript -Action Install -Directory $testDir
|
|
& $pathScript -Action Uninstall -Directory $testDir
|
|
$after = [string]$envKey.GetValue('Path', '', [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames)
|
|
if ($after -cne $preexisting -or $envKey.GetValueKind('Path') -ne [Microsoft.Win32.RegistryValueKind]::String) {
|
|
throw 'Uninstall changed a pre-existing user PATH entry.'
|
|
}
|
|
$envKey.DeleteValue('Path', $false)
|
|
& $pathScript -Action Install -Directory $testDir
|
|
& $pathScript -Action Uninstall -Directory $testDir
|
|
if (@($envKey.GetValueNames()) -icontains 'Path') { throw 'An originally absent PATH was recreated.' }
|
|
} finally {
|
|
if ($rawPresent) { $envKey.SetValue('Path', $rawBefore, $rawKind) } else { $envKey.DeleteValue('Path', $false) }
|
|
$envKey.Dispose()
|
|
# The safety check above established that this key did not exist. Refuse
|
|
# recursive deletion if anything unexpected was created under it.
|
|
[Microsoft.Win32.Registry]::CurrentUser.DeleteSubKey('Software\Aego', $false)
|
|
}
|
|
$workspace = $env:GITHUB_WORKSPACE
|
|
$portableZip = Join-Path $workspace '.cache\github-ci\dist\portable\aego-windows-amd64-portable.zip'
|
|
$portableDir = Join-Path $env:RUNNER_TEMP 'aego-ci-portable'
|
|
if (Test-Path $portableDir) { throw 'Portable smoke directory already exists.' }
|
|
Expand-Archive -Path $portableZip -DestinationPath $portableDir
|
|
foreach ($file in @('aego.exe', 'aego-editor.exe', 'VERSION', 'README.txt')) {
|
|
if (-not (Test-Path (Join-Path $portableDir $file) -PathType Leaf)) { throw "Missing portable $file" }
|
|
}
|
|
$previousProcessPath = $env:Path
|
|
try {
|
|
$env:Path = "$env:SystemRoot\System32;$env:SystemRoot"
|
|
& (Join-Path $portableDir 'aego.exe') version
|
|
if ($LASTEXITCODE -ne 0) { throw 'Portable CLI did not start with system-only PATH.' }
|
|
} finally { $env:Path = $previousProcessPath }
|
|
$setup = Join-Path $workspace '.cache\github-ci\dist\installer\aego-windows-amd64-setup.exe'
|
|
$proc = Start-Process -FilePath $setup -ArgumentList @('/S', "/D=$install") -Wait -PassThru
|
|
if ($proc.ExitCode -ne 0) { throw "Installer returned $($proc.ExitCode)" }
|
|
foreach ($file in @('aego.exe', 'aego-editor.exe', 'VERSION', 'README.txt', 'aego-path.ps1', 'setup.exe', 'uninstall.exe')) {
|
|
if (-not (Test-Path (Join-Path $install $file) -PathType Leaf)) { throw "Missing installed $file" }
|
|
}
|
|
foreach ($shortcut in @((Join-Path $startMenu 'Aego.lnk'), (Join-Path $startMenu 'Uninstall Aego.lnk'), $desktop)) {
|
|
if (-not (Test-Path $shortcut -PathType Leaf)) { throw "Missing shortcut: $shortcut" }
|
|
}
|
|
$shell = New-Object -ComObject WScript.Shell
|
|
if ($shell.CreateShortcut((Join-Path $startMenu 'Aego.lnk')).TargetPath -ne (Join-Path $install 'aego-editor.exe') -or
|
|
$shell.CreateShortcut((Join-Path $startMenu 'Uninstall Aego.lnk')).TargetPath -ne (Join-Path $install 'uninstall.exe') -or
|
|
$shell.CreateShortcut($desktop).TargetPath -ne (Join-Path $install 'aego-editor.exe')) {
|
|
throw 'A shortcut targets the wrong executable.'
|
|
}
|
|
foreach ($association in @(@('.aego', 'Aego.Project'), @('.aescene', 'Aego.Scene'), @('.aeprefab', 'Aego.Prefab'))) {
|
|
$actual = (Get-Item ("HKCU:\Software\Classes\" + $association[0])).GetValue('')
|
|
if ($actual -ne $association[1]) { throw "Incorrect file association for $($association[0])" }
|
|
}
|
|
if (([Environment]::GetEnvironmentVariable('Path', 'User') -split ';') -notcontains $install) {
|
|
throw 'Installer did not add install directory to user PATH.'
|
|
}
|
|
$previousProcessPath = $env:Path
|
|
try {
|
|
$env:Path = "$env:SystemRoot\System32;$env:SystemRoot"
|
|
& (Join-Path $install 'aego.exe') version
|
|
if ($LASTEXITCODE -ne 0) { throw 'Installed CLI did not start with system-only PATH.' }
|
|
} finally { $env:Path = $previousProcessPath }
|
|
& (Join-Path $install 'aego.exe') run (Join-Path $workspace '.cache\github-ci\project') --headless --frames 60
|
|
if ($LASTEXITCODE -ne 0) { throw 'Installed headless runtime failed.' }
|
|
$userData = Join-Path $install 'user-data'
|
|
New-Item -ItemType Directory -Path $userData | Out-Null
|
|
Set-Content -Path (Join-Path $userData 'keep.txt') -Value 'keep user data'
|
|
$proc = Start-Process -FilePath (Join-Path $install 'uninstall.exe') -ArgumentList '/S' -Wait -PassThru
|
|
if ($proc.ExitCode -ne 0) { throw "Uninstaller returned $($proc.ExitCode)" }
|
|
for ($i = 0; $i -lt 30 -and (Test-Path (Join-Path $install 'uninstall.exe')); $i++) { Start-Sleep -Seconds 1 }
|
|
foreach ($file in @('aego.exe', 'aego-editor.exe', 'VERSION', 'README.txt', 'aego-path.ps1', 'setup.exe', 'uninstall.exe')) {
|
|
if (Test-Path (Join-Path $install $file)) { throw "Uninstaller left $file" }
|
|
}
|
|
if (-not (Test-Path (Join-Path $userData 'keep.txt'))) { throw 'Uninstaller removed user data.' }
|
|
foreach ($shortcut in @($startMenu, $desktop)) { if (Test-Path $shortcut) { throw "Uninstaller left $shortcut" } }
|
|
foreach ($key in $registry) { if (Test-Path $key) { throw "Uninstaller left $key" } }
|
|
if ([Environment]::GetEnvironmentVariable('Path', 'User') -ne $beforePath) { throw 'User PATH was not restored.' }
|
|
Write-Host 'Silent install/uninstall smoke passed. No GUI interaction or signature validation was performed.'
|