diff options
Diffstat (limited to 'packaging/win/smoke-node-runtime.ps1')
| -rw-r--r-- | packaging/win/smoke-node-runtime.ps1 | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/packaging/win/smoke-node-runtime.ps1 b/packaging/win/smoke-node-runtime.ps1 new file mode 100644 index 0000000..bfcabac --- /dev/null +++ b/packaging/win/smoke-node-runtime.ps1 @@ -0,0 +1,107 @@ +<# +.SYNOPSIS + Start a frozen meshbay-node as a daemon and check it answers as the version + it claims to be. + +.DESCRIPTION + `meshbay-node --help` imports the parser and nothing else, so it passes for + a bundle that cannot start the daemon at all. This starts the real daemon, + in a throwaway profile (its own LOCALAPPDATA, an unused port, a hub URL + nothing listens on -- it never touches a real hub or the developer's own + node), waits for its control API, and checks: + - /api/status answers, with the expected version; + - the Windows log file was written (a service-mode daemon has no console, + and this file is the only place its errors go). + + Also useful against an installed build: + smoke-node-runtime.ps1 -Exe "$env:LOCALAPPDATA\Programs\MeshBay\resources\node-runtime\meshbay-node.exe" -ExpectVersion 0.16.0 + +.PARAMETER Exe + The meshbay-node.exe to start. + +.PARAMETER ExpectVersion + The version /api/status must report. +#> +[CmdletBinding()] +param( + [Parameter(Mandatory = $true)][string]$Exe, + [Parameter(Mandatory = $true)][string]$ExpectVersion, + [int]$TimeoutSeconds = 45 +) + +$ErrorActionPreference = "Stop" +Set-StrictMode -Version Latest + +$profileDir = Join-Path ([IO.Path]::GetTempPath()) ("meshbay-smoke-" + [guid]::NewGuid().ToString("N")) +$meshbay = Join-Path $profileDir "meshbay" +New-Item -ItemType Directory -Force $meshbay | Out-Null + +# A free loopback port, so a node already running here on 18000 is untouched. +$listener = [Net.Sockets.TcpListener]::new([Net.IPAddress]::Loopback, 0) +$listener.Start() +$port = $listener.LocalEndpoint.Port +$listener.Stop() + +$bytes = New-Object byte[] 32 +[Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($bytes) +$unlock = Join-Path $meshbay "unlock.key" +Set-Content -Encoding ascii -LiteralPath $unlock ([Convert]::ToBase64String($bytes)) +$unlockToml = $unlock.Replace([char]92, [char]47) +Set-Content -Encoding ascii -LiteralPath (Join-Path $meshbay "node.toml") @" +[hub] +url = "http://127.0.0.1:1" +username = "smoke" + +[node] +quic_enabled = false +ui_port = $port + +[keystore] +unlock_file = "$unlockToml" +"@ + +$oldLocal = $env:LOCALAPPDATA +$env:LOCALAPPDATA = $profileDir +$stderr = Join-Path $profileDir "stderr.txt" +$proc = $null +try { + $proc = Start-Process -FilePath $Exe -PassThru -WindowStyle Hidden ` + -RedirectStandardError $stderr -RedirectStandardOutput (Join-Path $profileDir "stdout.txt") + $env:LOCALAPPDATA = $oldLocal + + $tokenFile = Join-Path $meshbay "data\ui-token" + $status = $null + $deadline = (Get-Date).AddSeconds($TimeoutSeconds) + while ((Get-Date) -lt $deadline -and -not $proc.HasExited) { + if (Test-Path -LiteralPath $tokenFile) { + try { + $token = (Get-Content -LiteralPath $tokenFile -Raw).Trim() + $status = Invoke-RestMethod "http://127.0.0.1:$port/api/status?t=$token" -TimeoutSec 3 + break + } catch { } + } + Start-Sleep -Milliseconds 500 + } + + $tail = if (Test-Path -LiteralPath $stderr) { (Get-Content -LiteralPath $stderr -Tail 30) -join "`n" } else { "" } + if ($proc.HasExited) { + throw "the frozen daemon exited (code $($proc.ExitCode)) before its control API answered:`n$tail" + } + if ($null -eq $status) { + throw "the frozen daemon's control API did not answer within ${TimeoutSeconds}s:`n$tail" + } + if ($status.version -ne $ExpectVersion) { + throw "the frozen daemon reports version '$($status.version)', expected '$ExpectVersion'" + } + $log = Join-Path $meshbay "state\node.log" + if (-not (Test-Path -LiteralPath $log) -or (Get-Item -LiteralPath $log).Length -eq 0) { + throw "the frozen daemon wrote no log file at $log" + } + Write-Host "OK daemon answered: version $($status.version), status $($status.status), log $log" -ForegroundColor Green +} +finally { + $env:LOCALAPPDATA = $oldLocal + if ($proc -and -not $proc.HasExited) { Stop-Process -Id $proc.Id -Force -ErrorAction SilentlyContinue } + if ($proc) { $proc.WaitForExit(10000) | Out-Null } + Remove-Item -LiteralPath $profileDir -Recurse -Force -ErrorAction SilentlyContinue +} |