working install and uninstall flow in Vagrant

This commit is contained in:
2026-04-27 22:06:57 -05:00
parent ea006827f5
commit 506dfbd669
16 changed files with 1857 additions and 390 deletions
@@ -2,16 +2,120 @@
param(
[Parameter(Mandatory)][string]$InstallerPath,
[Parameter(Mandatory)][string]$ResultPath,
[int]$TimeoutSeconds = 600
[int]$TimeoutSeconds = 600,
[string]$TracePath = $(Join-Path (Split-Path -Parent $ResultPath) "trace"),
[string]$OperationName = "installer",
[string]$InstallerArgumentsBase64 = "",
[string[]]$InstallerArguments = @("--headed", "--automation")
)
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
function Write-TraceEvent {
param(
[Parameter(Mandatory)][string]$Phase,
[object]$Detail = $null
)
try {
New-Item -ItemType Directory -Force -Path $TracePath | Out-Null
$event = [ordered]@{
time = (Get-Date).ToUniversalTime().ToString("o")
pid = $PID
script = Split-Path -Leaf $PSCommandPath
phase = $Phase
detail = $Detail
}
$event | ConvertTo-Json -Depth 12 -Compress | Add-Content -LiteralPath (Join-Path $TracePath "guest-events.jsonl") -Encoding UTF8
}
catch {
Write-Warning "Failed to write trace event '$Phase': $($_.Exception.Message)"
}
}
function Write-DiagnosticFile {
param(
[Parameter(Mandatory)][string]$Name,
[Parameter(Mandatory)][scriptblock]$Capture
)
$path = Join-Path $TracePath $Name
try {
$value = & $Capture
$value | ConvertTo-Json -Depth 12 | Set-Content -LiteralPath $path -Encoding UTF8
}
catch {
[ordered]@{
error = $_.Exception.Message
type = $_.Exception.GetType().FullName
} | ConvertTo-Json -Depth 6 | Set-Content -LiteralPath $path -Encoding UTF8
}
}
function Export-InstallerDiagnostics {
param(
[Parameter(Mandatory)][string]$Reason,
[System.Diagnostics.Process]$InstallerProcess = $null
)
Write-TraceEvent -Phase "installer_diagnostics_start" -Detail @{ reason = $Reason; installerPid = $(if ($InstallerProcess) { $InstallerProcess.Id } else { $null }) }
Write-DiagnosticFile -Name "interactive-context.json" -Capture {
[ordered]@{
reason = $Reason
computerName = $env:COMPUTERNAME
userName = $env:USERNAME
sessionName = $env:SESSIONNAME
installerPath = $InstallerPath
installerArgs = $InstallerArguments
operationName = $OperationName
resultPath = $ResultPath
tracePath = $TracePath
timeoutSeconds = $TimeoutSeconds
installerPid = $(if ($InstallerProcess) { $InstallerProcess.Id } else { $null })
installerExited = $(if ($InstallerProcess) { $InstallerProcess.HasExited } else { $null })
}
}
Write-DiagnosticFile -Name "interactive-processes.json" -Capture {
Get-CimInstance Win32_Process |
Where-Object { $_.Name -match 'covenant|Covenant|powershell|pwsh|dotnet' } |
Select-Object ProcessId, ParentProcessId, Name, CommandLine, CreationDate
}
Write-DiagnosticFile -Name "interactive-windows.json" -Capture {
Get-Process |
Where-Object { $_.MainWindowHandle -ne 0 -or $_.ProcessName -match 'covenant|Covenant|powershell|pwsh' } |
Select-Object Id, ProcessName, MainWindowTitle, MainWindowHandle, StartTime
}
Write-DiagnosticFile -Name "interactive-application-events.json" -Capture {
Get-WinEvent -FilterHashtable @{ LogName = "Application"; StartTime = (Get-Date).AddHours(-2) } -MaxEvents 200 -ErrorAction SilentlyContinue |
Select-Object TimeCreated, Id, LevelDisplayName, ProviderName, Message
}
Write-TraceEvent -Phase "installer_diagnostics_finish" -Detail @{ reason = $Reason }
}
$installer = $null
$startedAt = Get-Date
try {
if (-not [string]::IsNullOrWhiteSpace($InstallerArgumentsBase64)) {
$argumentsJson = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($InstallerArgumentsBase64))
$decodedArguments = ConvertFrom-Json -InputObject $argumentsJson
$InstallerArguments = @()
foreach ($argument in $decodedArguments) {
$InstallerArguments += [string]$argument
}
}
New-Item -ItemType Directory -Force -Path $TracePath | Out-Null
Write-TraceEvent -Phase "interactive_installer_start" -Detail @{
installerPath = $InstallerPath
installerArgs = $InstallerArguments
operationName = $OperationName
resultPath = $ResultPath
tracePath = $TracePath
timeoutSeconds = $TimeoutSeconds
}
if (-not (Test-Path -LiteralPath $InstallerPath)) {
throw "Installer not found: $InstallerPath"
}
@@ -22,17 +126,47 @@ try {
}
Remove-Item -LiteralPath $ResultPath -Force -ErrorAction SilentlyContinue
$installer = Start-Process -FilePath $InstallerPath -ArgumentList @("--headed", "--automation") -PassThru
$env:COVENANT_SETUP_TRACE_DIR = $TracePath
Write-TraceEvent -Phase "trace_environment_set" -Detail @{ name = "COVENANT_SETUP_TRACE_DIR"; value = $TracePath }
if (-not $installer.WaitForExit($TimeoutSeconds * 1000)) {
Stop-Process -Id $installer.Id -Force -ErrorAction SilentlyContinue
throw "Installer timed out after $TimeoutSeconds seconds."
$installer = Start-Process -FilePath $InstallerPath -ArgumentList $InstallerArguments -PassThru
Write-TraceEvent -Phase "installer_process_started" -Detail @{ pid = $installer.Id; operationName = $OperationName }
$deadline = (Get-Date).AddSeconds($TimeoutSeconds)
$lastPoll = Get-Date "2000-01-01"
while (-not $installer.HasExited) {
if ((Get-Date) -ge $deadline) {
Export-InstallerDiagnostics -Reason "installer_timeout" -InstallerProcess $installer
Stop-Process -Id $installer.Id -Force -ErrorAction SilentlyContinue
throw "Installer timed out after $TimeoutSeconds seconds."
}
if (((Get-Date) - $lastPoll).TotalSeconds -ge 10) {
$lastPoll = Get-Date
$installer.Refresh()
Write-TraceEvent -Phase "installer_still_running" -Detail @{
pid = $installer.Id
operationName = $OperationName
elapsedSeconds = [int]((Get-Date) - $startedAt).TotalSeconds
responding = $installer.Responding
mainWindow = $installer.MainWindowTitle
}
}
Start-Sleep -Seconds 2
$installer.Refresh()
}
Write-TraceEvent -Phase "installer_process_exited" -Detail @{ pid = $installer.Id; exitCode = $installer.ExitCode; operationName = $OperationName }
Export-InstallerDiagnostics -Reason "installer_exit" -InstallerProcess $installer
$result = [ordered]@{
success = ($installer.ExitCode -eq 0)
exitCode = [int]$installer.ExitCode
installerPath = $InstallerPath
installerArgs = $InstallerArguments
operationName = $OperationName
tracePath = $TracePath
startedAt = $startedAt.ToString("o")
finishedAt = (Get-Date).ToString("o")
}
@@ -43,9 +177,15 @@ try {
}
}
catch {
Write-TraceEvent -Phase "interactive_installer_error" -Detail @{
error = $_.Exception.Message
type = $_.Exception.GetType().FullName
}
Export-InstallerDiagnostics -Reason "interactive_installer_error" -InstallerProcess $installer
$failure = [ordered]@{
success = $false
error = $_.Exception.Message
tracePath = $TracePath
startedAt = $startedAt.ToString("o")
finishedAt = (Get-Date).ToString("o")
}