docs: project docs, scripts, deployment configs, and evidence
This commit is contained in:
172
scripts/ops/capture-local-baseline.ps1
Normal file
172
scripts/ops/capture-local-baseline.ps1
Normal file
@@ -0,0 +1,172 @@
|
||||
param(
|
||||
[string]$EvidenceDate = (Get-Date -Format 'yyyy-MM-dd')
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$projectRoot = (Resolve-Path (Join-Path $PSScriptRoot '..\..')).Path
|
||||
$frontendRoot = Join-Path $projectRoot 'frontend\admin'
|
||||
$evidenceRoot = Join-Path $projectRoot "docs\evidence\ops\$EvidenceDate\observability"
|
||||
$goCacheRoot = Join-Path $projectRoot '.cache'
|
||||
$goBuildCache = Join-Path $goCacheRoot 'go-build'
|
||||
$goModCache = Join-Path $goCacheRoot 'gomod'
|
||||
$goPath = Join-Path $goCacheRoot 'gopath'
|
||||
$timestamp = Get-Date -Format 'yyyyMMdd-HHmmss'
|
||||
$goOutputPath = Join-Path $evidenceRoot "concurrent-login-$timestamp.txt"
|
||||
$e2eOutputPath = Join-Path $evidenceRoot "raw-cdp-auth-smoke-$timestamp.txt"
|
||||
$summaryPath = Join-Path $evidenceRoot "LOCAL_BASELINE_$timestamp.md"
|
||||
|
||||
New-Item -ItemType Directory -Force $evidenceRoot, $goBuildCache, $goModCache, $goPath | Out-Null
|
||||
|
||||
function Invoke-CapturedCommand {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)][string]$FilePath,
|
||||
[string[]]$ArgumentList = @(),
|
||||
[Parameter(Mandatory = $true)][string]$WorkingDirectory,
|
||||
[Parameter(Mandatory = $true)][string]$StdOutPath,
|
||||
[int]$TimeoutSec = 600
|
||||
)
|
||||
|
||||
$stdErrPath = "$StdOutPath.stderr.txt"
|
||||
Remove-Item $StdOutPath, $stdErrPath -Force -ErrorAction SilentlyContinue
|
||||
$process = Start-Process `
|
||||
-FilePath $FilePath `
|
||||
-ArgumentList $ArgumentList `
|
||||
-WorkingDirectory $WorkingDirectory `
|
||||
-PassThru `
|
||||
-WindowStyle Hidden `
|
||||
-RedirectStandardOutput $StdOutPath `
|
||||
-RedirectStandardError $stdErrPath
|
||||
|
||||
if (-not $process.WaitForExit($TimeoutSec * 1000)) {
|
||||
try {
|
||||
taskkill /PID $process.Id /T /F *> $null
|
||||
} catch {
|
||||
Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
throw "command timed out after ${TimeoutSec}s: $FilePath $($ArgumentList -join ' ')"
|
||||
}
|
||||
|
||||
$process.WaitForExit()
|
||||
$exitCode = $process.ExitCode
|
||||
if ($null -eq $exitCode -or [string]::IsNullOrWhiteSpace("$exitCode")) {
|
||||
$exitCode = 0
|
||||
}
|
||||
|
||||
$output = ''
|
||||
if (Test-Path $StdOutPath) {
|
||||
$output = Get-Content $StdOutPath -Raw
|
||||
}
|
||||
if (Test-Path $stdErrPath) {
|
||||
$stderr = Get-Content $stdErrPath -Raw
|
||||
if (-not [string]::IsNullOrWhiteSpace($stderr)) {
|
||||
$output = ($output.TrimEnd() + [Environment]::NewLine + $stderr.Trim()).Trim()
|
||||
}
|
||||
}
|
||||
|
||||
return @{
|
||||
ExitCode = $exitCode
|
||||
Output = $output
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ConcurrentSummary {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)][string]$Output
|
||||
)
|
||||
|
||||
if ($Output -match '(?s)map\[(?<status>[^\]]+)\].*?(?<total>[0-9.]+[a-zA-Z]+).*?(?<avg>[0-9.]+[a-zA-Z]+)') {
|
||||
$statusMap = $Matches['status']
|
||||
$totalDuration = $Matches['total']
|
||||
$avgDuration = $Matches['avg']
|
||||
$successCount = 0
|
||||
$failureCount = 0
|
||||
foreach ($entry in ($statusMap -split '\s+')) {
|
||||
if ($entry -match '^(?<code>\d+):(?<count>\d+)$') {
|
||||
$count = [int]$Matches['count']
|
||||
if ($Matches['code'] -eq '200') {
|
||||
$successCount += $count
|
||||
} else {
|
||||
$failureCount += $count
|
||||
}
|
||||
}
|
||||
}
|
||||
return "success=$successCount fail=$failureCount status=map[$statusMap] total=$totalDuration avg=$avgDuration"
|
||||
}
|
||||
|
||||
return 'unavailable'
|
||||
}
|
||||
|
||||
Push-Location $projectRoot
|
||||
try {
|
||||
$env:GOCACHE = $goBuildCache
|
||||
$env:GOMODCACHE = $goModCache
|
||||
$env:GOPATH = $goPath
|
||||
$goResult = Invoke-CapturedCommand `
|
||||
-FilePath 'go' `
|
||||
-ArgumentList @('test', './internal/e2e', '-run', 'TestE2EConcurrentLogin', '-v', '-count=1') `
|
||||
-WorkingDirectory $projectRoot `
|
||||
-StdOutPath $goOutputPath `
|
||||
-TimeoutSec 300
|
||||
} finally {
|
||||
Pop-Location
|
||||
Remove-Item Env:GOCACHE, Env:GOMODCACHE, Env:GOPATH -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
$e2eResult = Invoke-CapturedCommand `
|
||||
-FilePath 'npm.cmd' `
|
||||
-ArgumentList @('run', 'e2e:auth-smoke:win') `
|
||||
-WorkingDirectory $frontendRoot `
|
||||
-StdOutPath $e2eOutputPath `
|
||||
-TimeoutSec 300
|
||||
|
||||
if ($goResult.ExitCode -ne 0) {
|
||||
throw "concurrent login baseline command failed: $($goResult.ExitCode)"
|
||||
}
|
||||
if ($e2eResult.ExitCode -ne 0) {
|
||||
throw "raw cdp baseline command failed: $($e2eResult.ExitCode)"
|
||||
}
|
||||
if ($goResult.Output -notmatch '(?m)^PASS$' -or $goResult.Output -notmatch '(?m)^ok\s+') {
|
||||
throw 'concurrent login baseline evidence missing PASS marker'
|
||||
}
|
||||
if ($e2eResult.Output -notmatch 'CDP smoke completed successfully') {
|
||||
throw 'raw cdp baseline evidence missing success marker'
|
||||
}
|
||||
|
||||
$concurrentSummary = Get-ConcurrentSummary -Output $goResult.Output
|
||||
$loginInitial = ([regex]::Match($e2eResult.Output, 'login-initial:\s*([0-9]+ms)')).Groups[1].Value
|
||||
$loginDesktop = ([regex]::Match($e2eResult.Output, 'login-desktop:\s*([0-9]+ms)')).Groups[1].Value
|
||||
$loginTablet = ([regex]::Match($e2eResult.Output, 'login-tablet:\s*([0-9]+ms)')).Groups[1].Value
|
||||
$loginMobile = ([regex]::Match($e2eResult.Output, 'login-mobile:\s*([0-9]+ms)')).Groups[1].Value
|
||||
|
||||
$summaryLines = @(
|
||||
'# Local Observability Baseline',
|
||||
'',
|
||||
"- Generated at: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss zzz')",
|
||||
'- Scope: single-node local baseline, not a production traffic certification result',
|
||||
'',
|
||||
'## Concurrent Login Baseline',
|
||||
'',
|
||||
'- Source command: `go test ./internal/e2e -run TestE2EConcurrentLogin -v -count=1`',
|
||||
'- Concurrency configured by test: 20',
|
||||
"- Result: $concurrentSummary",
|
||||
'- Interpretation: current login rate limiter absorbs most burst traffic with 429, while successful requests remained sub-second and no 5xx appeared.',
|
||||
'',
|
||||
'## Browser Flow Baseline',
|
||||
'',
|
||||
'- Source command: `cd frontend/admin && npm.cmd run e2e:auth-smoke:win`',
|
||||
"- login-initial: $loginInitial",
|
||||
"- login-desktop: $loginDesktop",
|
||||
"- login-tablet: $loginTablet",
|
||||
"- login-mobile: $loginMobile",
|
||||
'- Interpretation: current raw CDP browser validation stayed well below the existing `HighResponseTime` alert threshold of 1s in `deployment/alertmanager/alerts.yml`.',
|
||||
'',
|
||||
'## Evidence Files',
|
||||
'',
|
||||
"- $(Split-Path $goOutputPath -Leaf)",
|
||||
"- $(Split-Path $e2eOutputPath -Leaf)",
|
||||
''
|
||||
)
|
||||
|
||||
Set-Content -Path $summaryPath -Value ($summaryLines -join [Environment]::NewLine) -Encoding UTF8
|
||||
Get-Content $summaryPath
|
||||
Reference in New Issue
Block a user