Public/Test-CCRepoHealth.ps1
|
function Test-CCRepoHealth { [CmdletBinding()] param( [string]$Path = '.', [ValidateSet('core','active','minimal')][string]$Standard = 'core', [string]$Config, [switch]$Detailed, [ValidateSet('Console','Json','Quiet')][string]$OutputFormat = 'Console', [ValidateSet('Error','Warning')][string]$FailOn ) $Path = (Resolve-Path $Path -ErrorAction Stop).Path $splat = @{ Path = $Path; Standard = $Standard; Config = $Config } $allResults = @() $allResults += Test-CCFilePresence @splat $allResults += Test-CCFolderStructure @splat $allResults += Test-CCDocumentation @splat $allResults += Test-CCDependencies @splat $allResults += Test-CCCIConfiguration @splat # Security checks inline (simple enough to not need a separate file) $cfg = Get-CCRepoConfig -Path $Path -Standard $Standard -ConfigFile $Config $disabled = $cfg['disabled_checks'] ?? @() # SEC-001: .gitignore covers secret patterns if ('SEC-001' -notin $disabled -and $cfg['security_forbidden'].Count -gt 0) { $gitignorePath = Join-Path $Path '.gitignore' if (Test-Path $gitignorePath) { $gitignoreContent = Get-Content $gitignorePath -Raw $uncovered = @() foreach ($pattern in $cfg['security_forbidden']) { if ($gitignoreContent -notmatch [regex]::Escape($pattern)) { $uncovered += $pattern } } if ($uncovered.Count -eq 0) { $allResults += New-CCRepoCheckResult -CheckId 'SEC-001' -Category 'Security' ` -Item '.gitignore secrets' -Status 'Pass' -Severity 'Error' ` -Message ".gitignore covers all secret patterns" -Standard $Standard } else { $allResults += New-CCRepoCheckResult -CheckId 'SEC-001' -Category 'Security' ` -Item '.gitignore secrets' -Status 'Warning' -Severity 'Warning' ` -Message ".gitignore missing patterns: $($uncovered -join ', ')" -Standard $Standard ` -FixAvailable $true -FixAction "Add patterns to .gitignore" } } else { $allResults += New-CCRepoCheckResult -CheckId 'SEC-001' -Category 'Security' ` -Item '.gitignore secrets' -Status 'Skipped' -Severity 'Error' ` -Message ".gitignore not found" -Standard $Standard } } # Output handling switch ($OutputFormat) { 'Json' { $allResults | ConvertTo-Json -Depth 5 } 'Quiet' { # No output, just set exit code } default { # Console output $pass = ($allResults | Where-Object Status -eq 'Pass').Count $fail = ($allResults | Where-Object Status -eq 'Fail').Count $warn = ($allResults | Where-Object Status -eq 'Warning').Count $skip = ($allResults | Where-Object Status -eq 'Skipped').Count if ($Detailed) { $grouped = $allResults | Group-Object Category foreach ($group in $grouped) { Write-Host "`n $($group.Name)" -ForegroundColor Cyan foreach ($r in $group.Group) { $icon = switch ($r.Status) { 'Pass' { '[PASS]' } 'Fail' { '[FAIL]' } 'Warning' { '[WARN]' } 'Skipped' { '[SKIP]' } } $color = switch ($r.Status) { 'Pass' { 'Green' } 'Fail' { 'Red' } 'Warning' { 'Yellow' } 'Skipped' { 'DarkGray' } } Write-Host " $icon $($r.CheckId): $($r.Message)" -ForegroundColor $color } } } Write-Host "`n Repository Health ($Standard): " -NoNewline if ($fail -eq 0) { Write-Host "HEALTHY" -ForegroundColor Green } else { Write-Host "$fail ISSUE(S)" -ForegroundColor Red } Write-Host " Pass: $pass | Fail: $fail | Warning: $warn | Skipped: $skip`n" $allResults } } # FailOn exit code if ($FailOn) { $failCount = switch ($FailOn) { 'Error' { ($allResults | Where-Object { $_.Status -eq 'Fail' -and $_.Severity -eq 'Error' }).Count } 'Warning' { ($allResults | Where-Object { $_.Status -in 'Fail','Warning' }).Count } } if ($failCount -gt 0) { $host.SetShouldExit(1) exit 1 } } } |