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

@@ -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