maksit-cluster-console/utils/tools/Invoke-Screenshots.ps1

219 lines
7.0 KiB
PowerShell

#requires -Version 7.0
#requires -PSEdition Core
<#
.SYNOPSIS
Opens Cluster Console and saves PNGs of the main screens.
.DESCRIPTION
Applies the screenshot window layout (including an expanded Connections
catalog), launches the UI with --screenshots, and writes one folder of PNGs
plus manifest.json. Closes the app when the tour finishes. Unless
-KeepLayout is set, settings.json is put back to the bytes from before this
script ran, so the tour does not leave a different page or window size behind.
Close Cluster Console first. The capture uses a live kubeconfig context.
Grids are shown unsorted and unfiltered, across all namespaces. Column widths stay as saved.
Each view produces <id>.png for the whole window.
catalog.png is the catalog column, saved once.
An empty resource table is skipped.
With no -Views, the tour opens every navigator page except discovered custom resources, then Connections,
the Cloud window, Settings → AI, and volume files. -Views cloud saves only the Cloud window and does not open a cluster.
Each resource page waits for rows, selects the first one, and saves
the window on the Overview tab. It then saves every other visible right-shoulder tab. Chat is omitted.
Further omissions are per navigator id. Data, Helm values, secret and ConfigMap YAML, Dapr component
YAML, and Helm manifests are blurred in the PNG. -Views limits the run to those navigator ids.
welcome is the shell before a cluster is opened.
PNGs are 96 DPI device pixels, so a 1600x900 window is a 1600x900 file.
.PARAMETER Context
Kubeconfig context to open. Omit to use the saved active context, or the
first context in the catalog.
.PARAMETER Views
Comma-separated navigator ids. Omit for the default tour.
.PARAMETER OutDir
Folder for the PNGs. Relative paths are under the repo root.
Default assets/screenshots.
.PARAMETER SettleMs
Pause after each view loads, so grids and charts can paint. Default 600.
.PARAMETER Exe
Path to MaksIT.ClusterConsole.UI.exe. Omit to use the newest build under src.
.PARAMETER Build
Build the UI project before launching.
.PARAMETER SkipLayout
Do not rewrite window size and pane widths before launch.
.PARAMETER KeepLayout
Leave settings.json as the tour finished. By default this script restores
the file it copied at startup.
.EXAMPLE
pwsh -File .\utils\tools\Invoke-Screenshots.ps1 -Context staging
.EXAMPLE
pwsh -File .\utils\tools\Invoke-Screenshots.ps1 -Context staging -Views "overview,pods,services"
#>
[CmdletBinding()]
param(
[string]$Context,
[string]$Views,
[string]$OutDir = "assets/screenshots",
[int]$SettleMs = 600,
[string]$Exe,
[switch]$Build,
[switch]$SkipLayout,
[switch]$KeepLayout,
[int]$Width = 1600,
[int]$Height = 900
)
$ErrorActionPreference = "Stop"
$repo = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent
$project = Join-Path $repo "src\MaksIT.ClusterConsole.UI\MaksIT.ClusterConsole.UI.csproj"
$layoutScript = Join-Path $PSScriptRoot "Set-ScreenshotLayout.ps1"
$settingsPath = Join-Path $env:APPDATA "MaksIT\Cluster Console\settings.json"
function Resolve-ConsoleExe {
if (-not [string]::IsNullOrWhiteSpace($Exe)) {
if (-not (Test-Path -LiteralPath $Exe)) {
Write-Error "Exe not found: $Exe"
}
return (Resolve-Path -LiteralPath $Exe).Path
}
$bin = Join-Path $repo "src\MaksIT.ClusterConsole.UI\bin"
$found = @()
if (Test-Path -LiteralPath $bin) {
$found = @(Get-ChildItem -Path $bin -Filter "MaksIT.ClusterConsole.UI.exe" -Recurse -File -ErrorAction SilentlyContinue)
}
$newest = $found | Sort-Object LastWriteTime -Descending | Select-Object -First 1
$stale = $newest -and (Test-UiSourcesNewer $newest.FullName)
if ($stale) {
Write-Host "UI sources are newer than $($newest.FullName). Rebuilding."
}
if ($Build -or $found.Count -eq 0 -or $stale) {
# Out-Host keeps build text visible without adding it to this function's
# success output (which would make $exePath an Object[] for Start-Process).
& dotnet build $project -c Debug --nologo | Out-Host
if ($LASTEXITCODE -ne 0) {
Write-Error "Build failed."
}
$found = @(Get-ChildItem -Path $bin -Filter "MaksIT.ClusterConsole.UI.exe" -Recurse -File)
}
if ($found.Count -eq 0) {
Write-Error "Could not find MaksIT.ClusterConsole.UI.exe. Pass -Build or -Exe."
}
$exe = ($found | Sort-Object LastWriteTime -Descending | Select-Object -First 1).FullName
return [string]$exe
}
function Test-UiSourcesNewer([string]$exePath) {
$exeTime = (Get-Item -LiteralPath $exePath).LastWriteTimeUtc
$src = Join-Path $repo "src"
foreach ($file in (Get-ChildItem -Path $src -Recurse -File)) {
if ($file.FullName -match '\\(bin|obj)\\') {
continue
}
if ($file.Extension -notin ".cs", ".axaml") {
continue
}
if ($file.LastWriteTimeUtc -gt $exeTime) {
return $true
}
}
return $false
}
if ($SettleMs -lt 0) {
Write-Error "SettleMs must be zero or greater."
}
if (-not [System.IO.Path]::IsPathRooted($OutDir)) {
$OutDir = Join-Path $repo $OutDir
}
$OutDir = [System.IO.Path]::GetFullPath($OutDir)
New-Item -ItemType Directory -Force -Path $OutDir | Out-Null
$snapshot = $null
if ((Test-Path -LiteralPath $settingsPath) -and -not $KeepLayout) {
$snapshot = Join-Path ([System.IO.Path]::GetTempPath()) ("cluster-console-settings-" + [guid]::NewGuid().ToString("n") + ".json")
Copy-Item -LiteralPath $settingsPath -Destination $snapshot
}
$code = 1
try {
if (-not $SkipLayout) {
& $layoutScript -Width $Width -Height $Height
}
$exePath = Resolve-ConsoleExe
$argList = @("--screenshots", $OutDir, "--settle-ms", "$SettleMs")
if (-not [string]::IsNullOrWhiteSpace($Context)) {
$argList += @("--context", $Context)
}
if (-not [string]::IsNullOrWhiteSpace($Views)) {
$argList += @("--views", $Views)
}
Write-Host "Launching $exePath"
Write-Host "Saving screenshots to $OutDir"
$proc = Start-Process -FilePath $exePath -ArgumentList $argList -Wait -PassThru
$code = $proc.ExitCode
}
finally {
if ($snapshot -and (Test-Path -LiteralPath $snapshot)) {
$running = Get-Process -Name "MaksIT.ClusterConsole.UI" -ErrorAction SilentlyContinue
if (-not $running) {
Copy-Item -LiteralPath $snapshot -Destination $settingsPath -Force
Remove-Item -LiteralPath $snapshot -Force
Write-Host "Restored $settingsPath"
}
else {
Write-Warning "Cluster Console is still running, so settings were left in place. Snapshot: $snapshot"
}
}
}
$manifestPath = Join-Path $OutDir "manifest.json"
if (Test-Path -LiteralPath $manifestPath) {
Write-Host (Get-Content -LiteralPath $manifestPath -Raw)
}
if ($code -ne 0) {
Write-Error "Cluster Console exited with code $code."
}
Write-Host "Screenshots are in $OutDir"