Add quiet validation wrapper

This commit is contained in:
2026-06-06 10:03:01 +02:00
parent 59c9b05d6c
commit 65c7716d62
5 changed files with 324 additions and 0 deletions

View File

@@ -42,6 +42,18 @@ cmake --preset windows-msvc-default
cmake --build --preset windows-msvc-default --config Debug --target PanoPainter pano_cli cmake --build --preset windows-msvc-default --config Debug --target PanoPainter pano_cli
``` ```
Quiet checkpoint validation, preferred when working through Codex token-limited
sessions:
```powershell
powershell -ExecutionPolicy Bypass -File scripts\automation\quiet-validate.ps1 -BuildTargets PanoPainter,pano_cli -TestRegex "pp_app_core|pano_cli_plan"
```
The quiet wrapper writes full command logs under `out/logs/quiet-validation`,
prints only a compact summary, and applies editable warning/noise filters from
`scripts/automation/quiet-validation-ignore.txt`. If a step fails, read the
reported log file instead of rerunning with verbose output.
Focused fast validation: Focused fast validation:
```powershell ```powershell

View File

@@ -58,6 +58,16 @@ dependencies until each platform triplet is proven.
These commands are the current local baseline. These commands are the current local baseline.
Prefer the quiet wrapper for Codex checkpoint validation because it captures
full logs in `out/logs/quiet-validation`, emits only per-step summaries, and
keeps known warning/noise filters in
`scripts/automation/quiet-validation-ignore.txt`:
```powershell
powershell -ExecutionPolicy Bypass -File scripts\automation\quiet-validate.ps1 -BuildTargets PanoPainter,pano_cli -TestRegex "pp_app_core|pano_cli_plan"
powershell -ExecutionPolicy Bypass -File scripts\automation\quiet-validate.ps1 -BuildTargets pp_app_core_app_dialog_tests,pp_ui_core_overlay_lifetime_tests -TestRegex "pp_(app_core_app_dialog|ui_core_(node_lifetime|overlay_lifetime))"
```
```powershell ```powershell
cmake --preset windows-msvc-default cmake --preset windows-msvc-default
cmake --build --preset windows-msvc-default --config Debug --target PanoPainter cmake --build --preset windows-msvc-default --config Debug --target PanoPainter

View File

@@ -1716,6 +1716,7 @@ cmake --build --preset windows-msvc-default --config Debug --target pp_foundatio
ctest --preset desktop-fast --build-config Debug ctest --preset desktop-fast --build-config Debug
ctest --preset fuzz --build-config Debug ctest --preset fuzz --build-config Debug
ctest --preset stress --build-config Debug ctest --preset stress --build-config Debug
powershell -ExecutionPolicy Bypass -File scripts\automation\quiet-validate.ps1 -BuildTargets PanoPainter,pano_cli -TestRegex "pp_app_core|pano_cli_plan"
powershell -ExecutionPolicy Bypass -File scripts\automation\test.ps1 -Preset desktop-fast -Configuration Debug powershell -ExecutionPolicy Bypass -File scripts\automation\test.ps1 -Preset desktop-fast -Configuration Debug
powershell -ExecutionPolicy Bypass -File scripts\automation\build.ps1 -Preset windows-msvc-default -Configuration Debug -Target pano_cli powershell -ExecutionPolicy Bypass -File scripts\automation\build.ps1 -Preset windows-msvc-default -Configuration Debug -Target pano_cli
cmake --build --preset windows-msvc-default --target panopainter_validate_shaders cmake --build --preset windows-msvc-default --target panopainter_validate_shaders

View File

@@ -0,0 +1,288 @@
[CmdletBinding()]
param(
[string]$BuildPreset = "windows-msvc-default",
[string]$Configuration = "Debug",
[string[]]$BuildTargets = @("PanoPainter", "pano_cli"),
[string]$TestPreset = "desktop-fast",
[string]$TestRegex = "",
[switch]$Configure,
[switch]$SkipBuild,
[switch]$SkipTests,
[string]$CMakeCommand = "",
[string]$CTestCommand = "",
[string]$LogDir = "out/logs/quiet-validation",
[string]$IgnoreFilterFile = "",
[string[]]$IgnorePattern = @(),
[int]$FailureTailLines = 0
)
$ErrorActionPreference = "Stop"
function Resolve-CMakeCommand {
param([string]$Requested)
if ($Requested.Length -gt 0) {
return $Requested
}
$vsCmake = "C:\Program Files\Microsoft Visual Studio\18\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe"
if (Test-Path -LiteralPath $vsCmake) {
return $vsCmake
}
return "cmake"
}
function Resolve-CTestCommand {
param(
[string]$Requested,
[string]$ResolvedCMake
)
if ($Requested.Length -gt 0) {
return $Requested
}
if ($ResolvedCMake.EndsWith("cmake.exe", [System.StringComparison]::OrdinalIgnoreCase)) {
$candidate = Join-Path -Path (Split-Path -Parent $ResolvedCMake) -ChildPath "ctest.exe"
if (Test-Path -LiteralPath $candidate) {
return $candidate
}
}
return "ctest"
}
function Read-IgnorePatterns {
param(
[string]$FilterFile,
[string[]]$InlinePatterns
)
$patterns = @()
if ($FilterFile.Length -eq 0) {
$defaultFile = Join-Path -Path $PSScriptRoot -ChildPath "quiet-validation-ignore.txt"
if (Test-Path -LiteralPath $defaultFile) {
$FilterFile = $defaultFile
}
}
if ($FilterFile.Length -gt 0 -and (Test-Path -LiteralPath $FilterFile)) {
$patterns += Get-Content -LiteralPath $FilterFile |
Where-Object { $_.Trim().Length -gt 0 -and -not $_.TrimStart().StartsWith("#") }
}
$patterns += $InlinePatterns
return @($patterns | Where-Object { $_ -and $_.Length -gt 0 })
}
function Expand-ArgumentList {
param([string[]]$Values)
$expanded = @()
foreach ($value in $Values) {
if ($null -eq $value) {
continue
}
$expanded += $value -split "[,\s]+" | Where-Object { $_.Length -gt 0 }
}
return @($expanded)
}
function Test-IgnoredLine {
param(
[string]$Line,
[string[]]$Patterns
)
foreach ($pattern in $Patterns) {
if ($Line -match $pattern) {
return $true
}
}
return $false
}
function Measure-Log {
param(
[string]$Path,
[string[]]$IgnorePatterns
)
$errorPattern = "(?i)(:\s*(fatal\s+)?error\s+[A-Z0-9]+:|^LINK\s*:\s*fatal error|^CMake Error|Errors while running CTest|Unable to find executable|\*\*\*Failed)"
$warningPattern = "(?i)(:\s*warning\s+[A-Z0-9]+:|^LINK\s*:\s*warning\s+[A-Z0-9]+:|warning:)"
$ctestSummaryPattern = "(\d+)% tests passed, (\d+) tests failed out of (\d+)"
$lineCount = 0
$rawErrors = 0
$rawWarnings = 0
$visibleErrors = 0
$visibleWarnings = 0
$ignoredErrors = 0
$ignoredWarnings = 0
$testsFailed = $null
$testsTotal = $null
if (Test-Path -LiteralPath $Path) {
foreach ($line in Get-Content -LiteralPath $Path) {
++$lineCount
$ignored = Test-IgnoredLine -Line $line -Patterns $IgnorePatterns
if ($line -match $ctestSummaryPattern) {
$testsFailed = [int]$Matches[2]
$testsTotal = [int]$Matches[3]
}
if ($line -match $errorPattern) {
++$rawErrors
if ($ignored) { ++$ignoredErrors } else { ++$visibleErrors }
}
if ($line -match $warningPattern) {
++$rawWarnings
if ($ignored) { ++$ignoredWarnings } else { ++$visibleWarnings }
}
}
}
return [ordered]@{
lineCount = $lineCount
errors = $visibleErrors
warnings = $visibleWarnings
rawErrors = $rawErrors
rawWarnings = $rawWarnings
ignoredErrors = $ignoredErrors
ignoredWarnings = $ignoredWarnings
testsFailed = $testsFailed
testsTotal = $testsTotal
}
}
function Invoke-QuietStep {
param(
[string]$Name,
[string]$Command,
[string[]]$Arguments,
[string]$LogPath,
[string[]]$IgnorePatterns,
[int]$FailureTailLines
)
$started = Get-Date
$exitCode = 0
try {
& $Command @Arguments *> $LogPath
$exitCode = $LASTEXITCODE
if ($null -eq $exitCode) {
$exitCode = 0
}
}
catch {
$_ | Out-File -LiteralPath $LogPath -Append -Encoding utf8
$exitCode = 1
}
$elapsed = [int]((Get-Date) - $started).TotalMilliseconds
$summary = Measure-Log -Path $LogPath -IgnorePatterns $IgnorePatterns
$result = [ordered]@{
name = $Name
exitCode = $exitCode
elapsedMs = $elapsed
log = $LogPath
summary = $summary
}
if ($exitCode -ne 0 -and $FailureTailLines -gt 0 -and (Test-Path -LiteralPath $LogPath)) {
$result.failureTail = @(Get-Content -LiteralPath $LogPath -Tail $FailureTailLines)
}
return $result
}
$resolvedCMake = Resolve-CMakeCommand -Requested $CMakeCommand
$resolvedCTest = Resolve-CTestCommand -Requested $CTestCommand -ResolvedCMake $resolvedCMake
$BuildTargets = @(Expand-ArgumentList -Values $BuildTargets)
$IgnorePattern = @(Expand-ArgumentList -Values $IgnorePattern)
$ignorePatterns = Read-IgnorePatterns -FilterFile $IgnoreFilterFile -InlinePatterns $IgnorePattern
New-Item -ItemType Directory -Force -Path $LogDir | Out-Null
$runId = Get-Date -Format "yyyyMMdd-HHmmss"
$started = Get-Date
$results = @()
$overallExitCode = 0
if ($Configure) {
$log = Join-Path -Path $LogDir -ChildPath "$runId-configure-$BuildPreset.log"
$result = Invoke-QuietStep `
-Name "configure:$BuildPreset" `
-Command $resolvedCMake `
-Arguments @("--preset", $BuildPreset) `
-LogPath $log `
-IgnorePatterns $ignorePatterns `
-FailureTailLines $FailureTailLines
$results += $result
if ($result.exitCode -ne 0 -and $overallExitCode -eq 0) {
$overallExitCode = $result.exitCode
}
}
if (-not $SkipBuild) {
$targets = @($BuildTargets | Where-Object { $_ -and $_.Length -gt 0 })
if ($targets.Count -gt 0) {
$safeTargets = ($targets -join "_") -replace "[^A-Za-z0-9_.-]", "_"
$log = Join-Path -Path $LogDir -ChildPath "$runId-build-$BuildPreset-$Configuration-$safeTargets.log"
$buildArgs = @("--build", "--preset", $BuildPreset, "--config", $Configuration, "--target") + $targets
$result = Invoke-QuietStep `
-Name ("build:{0}:{1}" -f $BuildPreset, $Configuration) `
-Command $resolvedCMake `
-Arguments $buildArgs `
-LogPath $log `
-IgnorePatterns $ignorePatterns `
-FailureTailLines $FailureTailLines
$result.targets = $targets
$results += $result
if ($result.exitCode -ne 0 -and $overallExitCode -eq 0) {
$overallExitCode = $result.exitCode
}
}
}
if (-not $SkipTests) {
$safeRegex = if ($TestRegex.Length -gt 0) { ($TestRegex -replace "[^A-Za-z0-9_.-]", "_") } else { "all" }
$log = Join-Path -Path $LogDir -ChildPath "$runId-test-$TestPreset-$Configuration-$safeRegex.log"
$testArgs = @("--preset", $TestPreset, "--build-config", $Configuration, "--output-on-failure")
if ($TestRegex.Length -gt 0) {
$testArgs += @("-R", $TestRegex)
}
$result = Invoke-QuietStep `
-Name ("test:{0}:{1}" -f $TestPreset, $Configuration) `
-Command $resolvedCTest `
-Arguments $testArgs `
-LogPath $log `
-IgnorePatterns $ignorePatterns `
-FailureTailLines $FailureTailLines
if ($TestRegex.Length -gt 0) {
$result.testRegex = $TestRegex
}
$results += $result
if ($result.exitCode -ne 0 -and $overallExitCode -eq 0) {
$overallExitCode = $result.exitCode
}
}
$elapsed = [int]((Get-Date) - $started).TotalMilliseconds
$summaryPath = Join-Path -Path $LogDir -ChildPath "$runId-summary.json"
$payload = [ordered]@{
command = "quiet-validate"
exitCode = $overallExitCode
elapsedMs = $elapsed
buildPreset = $BuildPreset
configuration = $Configuration
testPreset = $TestPreset
logDir = $LogDir
summary = $summaryPath
ignoreFilterFile = $IgnoreFilterFile
ignorePatternCount = $ignorePatterns.Count
results = $results
}
$payload | ConvertTo-Json -Depth 8 | Out-File -LiteralPath $summaryPath -Encoding utf8
$payload | ConvertTo-Json -Compress -Depth 8
exit $overallExitCode

View File

@@ -0,0 +1,13 @@
# Regex patterns for warnings/noise hidden from quiet validation summaries.
# The full logs still contain these lines; this file only affects visible counts.
The vcpkg manifest was disabled
warning C4201:
warning C4267:
warning C5311:
warning C4018:
warning C4244:
warning C4189:
warning C4305:
warning C4099:
warning LNK4099: PDB 'yuv\.pdb'
warning LNK4098: defaultlib 'MSVCRT' conflicts