517 lines
17 KiB
PowerShell
517 lines
17 KiB
PowerShell
# ci-hooks.ps1 - Continuous integration hooks for .agents (PowerShell version)
|
|
# Part of LCBP3-DMS Phase 3 enhancements
|
|
|
|
param(
|
|
[Parameter(Mandatory=$false)]
|
|
[ValidateSet("pre-commit", "pre-push", "ci-pipeline", "install-hooks", "help")]
|
|
[string]$Command = "help"
|
|
)
|
|
|
|
# Configuration
|
|
$BaseDir = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
|
|
$AgentsDir = Join-Path $BaseDir ".agents"
|
|
$CILogDir = Join-Path $AgentsDir "logs\ci"
|
|
$CIReportDir = Join-Path $AgentsDir "reports\ci"
|
|
|
|
# Ensure directories exist
|
|
if (-not (Test-Path $CILogDir)) { New-Item -ItemType Directory -Path $CILogDir -Force | Out-Null }
|
|
if (-not (Test-Path $CIReportDir)) { New-Item -ItemType Directory -Path $CIReportDir -Force | Out-Null }
|
|
|
|
# Colors for output
|
|
$Colors = @{
|
|
Red = "`e[0;31m"
|
|
Green = "`e[0;32m"
|
|
Yellow = "`e[1;33m"
|
|
Blue = "`e[0;34m"
|
|
NoColor = "`e[0m"
|
|
}
|
|
|
|
# Logging function
|
|
function Write-CILog {
|
|
param(
|
|
[string]$Level,
|
|
[string]$Message
|
|
)
|
|
|
|
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
|
$logFile = Join-Path $CILogDir "ci-$(Get-Date -Format 'yyyy-MM-dd').log"
|
|
"$timestamp [$Level] $Message" | Out-File -FilePath $logFile -Append
|
|
|
|
# Console output with colors
|
|
switch ($Level) {
|
|
"INFO" { Write-Host $Message -ForegroundColor $Colors.Blue }
|
|
"PASS" { Write-Host $Message -ForegroundColor $Colors.Green }
|
|
"WARN" { Write-Host $Message -ForegroundColor $Colors.Yellow }
|
|
"FAIL" { Write-Host $Message -ForegroundColor $Colors.Red }
|
|
default { Write-Host $Message }
|
|
}
|
|
}
|
|
|
|
# Pre-commit hook
|
|
function Invoke-PreCommitHook {
|
|
Write-CILog "INFO" "Running pre-commit validation..."
|
|
|
|
$exitCode = 0
|
|
|
|
# 1. Run version validation
|
|
Write-CILog "INFO" "Checking version consistency..."
|
|
$versionScript = Join-Path $AgentsDir "scripts\powershell\validate-versions.ps1"
|
|
if (Test-Path $versionScript) {
|
|
try {
|
|
& $versionScript | Out-File -FilePath (Join-Path $CILogDir "pre-commit-versions.log") -Append
|
|
Write-CILog "PASS" "Version validation passed"
|
|
} catch {
|
|
Write-CILog "FAIL" "Version validation failed"
|
|
$exitCode = 1
|
|
}
|
|
} else {
|
|
Write-CILog "WARN" "Version validation script not found"
|
|
}
|
|
|
|
# 2. Run skill audit
|
|
Write-CILog "INFO" "Auditing skills..."
|
|
$auditScript = Join-Path $AgentsDir "scripts\powershell\audit-skills.ps1"
|
|
if (Test-Path $auditScript) {
|
|
try {
|
|
& $auditScript | Out-File -FilePath (Join-Path $CILogDir "pre-commit-skills.log") -Append
|
|
Write-CILog "PASS" "Skill audit passed"
|
|
} catch {
|
|
Write-CILog "FAIL" "Skill audit failed"
|
|
$exitCode = 1
|
|
}
|
|
} else {
|
|
Write-CILog "WARN" "Skill audit script not found"
|
|
}
|
|
|
|
# 3. Run integration tests (if Node.js available)
|
|
if (Get-Command node -ErrorAction SilentlyContinue) {
|
|
Write-CILog "INFO" "Running integration tests..."
|
|
$testScript = Join-Path $AgentsDir "tests\skill-integration.test.js"
|
|
if (Test-Path $testScript) {
|
|
try {
|
|
node $testScript | Out-File -FilePath (Join-Path $CILogDir "pre-commit-tests.log") -Append
|
|
Write-CILog "PASS" "Integration tests passed"
|
|
} catch {
|
|
Write-CILog "WARN" "Integration tests failed (non-blocking)"
|
|
}
|
|
} else {
|
|
Write-CILog "WARN" "Integration test script not found"
|
|
}
|
|
} else {
|
|
Write-CILog "WARN" "Node.js not available, skipping integration tests"
|
|
}
|
|
|
|
# 4. Check for forbidden patterns
|
|
Write-CILog "INFO" "Checking for forbidden patterns..."
|
|
$forbiddenPatterns = @("TODO", "FIXME", "XXX", "HACK")
|
|
$foundForbidden = $false
|
|
|
|
foreach ($pattern in $forbiddenPatterns) {
|
|
$skillsDir = Join-Path $AgentsDir "skills"
|
|
if (Test-Path $skillsDir) {
|
|
$matches = Select-String -Path $skillsDir\*.md -Pattern $pattern -Recurse
|
|
if ($matches) {
|
|
Write-CILog "WARN" "Found forbidden pattern: $pattern"
|
|
$foundForbidden = $true
|
|
}
|
|
}
|
|
}
|
|
|
|
if (-not $foundForbidden) {
|
|
Write-CILog "PASS" "No forbidden patterns found"
|
|
}
|
|
|
|
# Generate pre-commit report
|
|
$reportFile = Join-Path $CIReportDir "pre-commit-$(Get-Date -Format 'yyyyMMdd-HHmmss').json"
|
|
$report = @{
|
|
timestamp = (Get-Date -Format "yyyy-MM-ddTHH:mm:sszzz")
|
|
hook_type = "pre-commit"
|
|
exit_code = $exitCode
|
|
checks_performed = @(
|
|
"version_validation",
|
|
"skill_audit",
|
|
"integration_tests",
|
|
"forbidden_patterns"
|
|
)
|
|
log_files = @(
|
|
"pre-commit-versions.log",
|
|
"pre-commit-skills.log",
|
|
"pre-commit-tests.log"
|
|
)
|
|
}
|
|
$report | ConvertTo-Json -Depth 10 | Out-File -FilePath $reportFile
|
|
|
|
Write-CILog "INFO" "Pre-commit report saved to: $reportFile"
|
|
|
|
if ($exitCode -eq 0) {
|
|
Write-CILog "PASS" "Pre-commit validation completed successfully"
|
|
} else {
|
|
Write-CILog "FAIL" "Pre-commit validation failed"
|
|
}
|
|
|
|
return $exitCode
|
|
}
|
|
|
|
# Pre-push hook
|
|
function Invoke-PrePushHook {
|
|
Write-CILog "INFO" "Running pre-push validation..."
|
|
|
|
$exitCode = 0
|
|
|
|
# 1. Full health check
|
|
Write-CILog "INFO" "Running full health check..."
|
|
if (Get-Command node -ErrorAction SilentlyContinue) {
|
|
$healthScript = Join-Path $AgentsDir "scripts\health-monitor.js"
|
|
if (Test-Path $healthScript) {
|
|
try {
|
|
node $healthScript | Out-File -FilePath (Join-Path $CILogDir "pre-push-health.log") -Append
|
|
Write-CILog "PASS" "Health check passed"
|
|
} catch {
|
|
Write-CILog "FAIL" "Health check failed"
|
|
$exitCode = 1
|
|
}
|
|
} else {
|
|
Write-CILog "WARN" "Health monitor script not found"
|
|
}
|
|
} else {
|
|
Write-CILog "WARN" "Node.js not available, using basic health check"
|
|
$auditScript = Join-Path $AgentsDir "scripts\powershell\audit-skills.ps1"
|
|
if (Test-Path $auditScript) {
|
|
try {
|
|
& $auditScript | Out-File -FilePath (Join-Path $CILogDir "pre-push-basic.log") -Append
|
|
Write-CILog "PASS" "Basic health check passed"
|
|
} catch {
|
|
Write-CILog "FAIL" "Basic health check failed"
|
|
$exitCode = 1
|
|
}
|
|
}
|
|
}
|
|
|
|
# 2. Advanced validation (if available)
|
|
if (Get-Command node -ErrorAction SilentlyContinue) {
|
|
$advancedScript = Join-Path $AgentsDir "scripts\advanced-validator.js"
|
|
if (Test-Path $advancedScript) {
|
|
Write-CILog "INFO" "Running advanced validation..."
|
|
try {
|
|
node $advancedScript | Out-File -FilePath (Join-Path $CILogDir "pre-push-advanced.log") -Append
|
|
Write-CILog "PASS" "Advanced validation passed"
|
|
} catch {
|
|
Write-CILog "WARN" "Advanced validation found issues (non-blocking)"
|
|
}
|
|
}
|
|
}
|
|
|
|
# 3. Dependency validation
|
|
if (Get-Command node -ErrorAction SilentlyContinue) {
|
|
$dependencyScript = Join-Path $AgentsDir "scripts\dependency-validator.js"
|
|
if (Test-Path $dependencyScript) {
|
|
Write-CILog "INFO" "Running dependency validation..."
|
|
try {
|
|
node $dependencyScript | Out-File -FilePath (Join-Path $CILogDir "pre-push-dependencies.log") -Append
|
|
Write-CILog "PASS" "Dependency validation passed"
|
|
} catch {
|
|
Write-CILog "WARN" "Dependency validation found issues (non-blocking)"
|
|
}
|
|
}
|
|
}
|
|
|
|
# 4. Performance monitoring
|
|
if (Get-Command node -ErrorAction SilentlyContinue) {
|
|
$performanceScript = Join-Path $AgentsDir "scripts\performance-monitor.js"
|
|
if (Test-Path $performanceScript) {
|
|
Write-CILog "INFO" "Running performance monitoring..."
|
|
try {
|
|
node $performanceScript | Out-File -FilePath (Join-Path $CILogDir "pre-push-performance.log") -Append
|
|
Write-CILog "PASS" "Performance monitoring passed"
|
|
} catch {
|
|
Write-CILog "WARN" "Performance monitoring found issues (non-blocking)"
|
|
}
|
|
}
|
|
}
|
|
|
|
# Generate pre-push report
|
|
$reportFile = Join-Path $CIReportDir "pre-push-$(Get-Date -Format 'yyyyMMdd-HHmmss').json"
|
|
$report = @{
|
|
timestamp = (Get-Date -Format "yyyy-MM-ddTHH:mm:sszzz")
|
|
hook_type = "pre-push"
|
|
exit_code = $exitCode
|
|
checks_performed = @(
|
|
"health_check",
|
|
"advanced_validation",
|
|
"dependency_validation",
|
|
"performance_monitoring"
|
|
)
|
|
log_files = @(
|
|
"pre-push-health.log",
|
|
"pre-push-advanced.log",
|
|
"pre-push-dependencies.log",
|
|
"pre-push-performance.log"
|
|
)
|
|
}
|
|
$report | ConvertTo-Json -Depth 10 | Out-File -FilePath $reportFile
|
|
|
|
Write-CILog "INFO" "Pre-push report saved to: $reportFile"
|
|
|
|
if ($exitCode -eq 0) {
|
|
Write-CILog "PASS" "Pre-push validation completed successfully"
|
|
} else {
|
|
Write-CILog "FAIL" "Pre-push validation failed"
|
|
}
|
|
|
|
return $exitCode
|
|
}
|
|
|
|
# CI pipeline hook
|
|
function Invoke-CIPipelineHook {
|
|
Write-CILog "INFO" "Running CI pipeline validation..."
|
|
|
|
$exitCode = 0
|
|
$pipelineStart = Get-Date
|
|
|
|
# Create pipeline workspace
|
|
$workspace = Join-Path $CIReportDir "pipeline-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
|
|
New-Item -ItemType Directory -Path $workspace -Force | Out-Null
|
|
|
|
# 1. Environment validation
|
|
Write-CILog "INFO" "Validating CI environment..."
|
|
|
|
# Check required tools
|
|
$requiredTools = @("node", "npm")
|
|
foreach ($tool in $requiredTools) {
|
|
if (Get-Command $tool -ErrorAction SilentlyContinue) {
|
|
Write-CILog "PASS" "Tool available: $tool"
|
|
} else {
|
|
Write-CILog "FAIL" "Tool missing: $tool"
|
|
$exitCode = 1
|
|
}
|
|
}
|
|
|
|
# Check Node.js modules
|
|
$packageJson = Join-Path $AgentsDir "package.json"
|
|
if (Test-Path $packageJson) {
|
|
Push-Location $AgentsDir
|
|
try {
|
|
npm list --depth=0 | Out-Null
|
|
Write-CILog "PASS" "Node.js dependencies installed"
|
|
} catch {
|
|
Write-CILog "WARN" "Installing Node.js dependencies..."
|
|
npm install | Out-File -FilePath (Join-Path $workspace "npm-install.log")
|
|
if ($LASTEXITCODE -ne 0) {
|
|
Write-CILog "FAIL" "Failed to install Node.js dependencies"
|
|
$exitCode = 1
|
|
}
|
|
}
|
|
Pop-Location
|
|
}
|
|
|
|
# 2. Full test suite
|
|
Write-CILog "INFO" "Running full test suite..."
|
|
|
|
# Integration tests
|
|
$integrationTest = Join-Path $AgentsDir "tests\skill-integration.test.js"
|
|
if (Test-Path $integrationTest) {
|
|
try {
|
|
node $integrationTest | Out-File -FilePath (Join-Path $workspace "integration-tests.log")
|
|
Write-CILog "PASS" "Integration tests passed"
|
|
} catch {
|
|
Write-CILog "FAIL" "Integration tests failed"
|
|
$exitCode = 1
|
|
}
|
|
}
|
|
|
|
# Workflow validation tests
|
|
$workflowTest = Join-Path $AgentsDir "tests\workflow-validation.test.js"
|
|
if (Test-Path $workflowTest) {
|
|
try {
|
|
node $workflowTest | Out-File -FilePath (Join-Path $workspace "workflow-tests.log")
|
|
Write-CILog "PASS" "Workflow validation tests passed"
|
|
} catch {
|
|
Write-CILog "FAIL" "Workflow validation tests failed"
|
|
$exitCode = 1
|
|
}
|
|
}
|
|
|
|
# 3. Comprehensive validation
|
|
Write-CILog "INFO" "Running comprehensive validation..."
|
|
|
|
# Health monitoring
|
|
$healthScript = Join-Path $AgentsDir "scripts\health-monitor.js"
|
|
if (Test-Path $healthScript) {
|
|
try {
|
|
node $healthScript | Out-File -FilePath (Join-Path $workspace "health-check.log")
|
|
Write-CILog "PASS" "Health monitoring passed"
|
|
} catch {
|
|
Write-CILog "FAIL" "Health monitoring failed"
|
|
$exitCode = 1
|
|
}
|
|
}
|
|
|
|
# Advanced validation
|
|
$advancedScript = Join-Path $AgentsDir "scripts\advanced-validator.js"
|
|
if (Test-Path $advancedScript) {
|
|
try {
|
|
node $advancedScript | Out-File -FilePath (Join-Path $workspace "advanced-validation.log")
|
|
Write-CILog "PASS" "Advanced validation passed"
|
|
} catch {
|
|
Write-CILog "WARN" "Advanced validation found issues"
|
|
}
|
|
}
|
|
|
|
# Dependency validation
|
|
$dependencyScript = Join-Path $AgentsDir "scripts\dependency-validator.js"
|
|
if (Test-Path $dependencyScript) {
|
|
try {
|
|
node $dependencyScript | Out-File -FilePath (Join-Path $workspace "dependency-validation.log")
|
|
Write-CILog "PASS" "Dependency validation passed"
|
|
} catch {
|
|
Write-CILog "WARN" "Dependency validation found issues"
|
|
}
|
|
}
|
|
|
|
# Performance monitoring
|
|
$performanceScript = Join-Path $AgentsDir "scripts\performance-monitor.js"
|
|
if (Test-Path $performanceScript) {
|
|
try {
|
|
node $performanceScript | Out-File -FilePath (Join-Path $workspace "performance-monitor.log")
|
|
Write-CILog "PASS" "Performance monitoring passed"
|
|
} catch {
|
|
Write-CILog "WARN" "Performance monitoring found issues"
|
|
}
|
|
}
|
|
|
|
# 4. Generate artifacts
|
|
Write-CILog "INFO" "Generating CI artifacts..."
|
|
|
|
$pipelineEnd = Get-Date
|
|
$duration = ($pipelineEnd - $pipelineStart).TotalSeconds
|
|
|
|
# Consolidated report
|
|
$reportFile = Join-Path $workspace "ci-pipeline-report.json"
|
|
$report = @{
|
|
timestamp = (Get-Date -Format "yyyy-MM-ddTHH:mm:sszzz")
|
|
pipeline_type = "full_ci"
|
|
duration_seconds = [int]$duration
|
|
exit_code = $exitCode
|
|
environment = @{
|
|
node_version = (node --version)
|
|
platform = $env:OS
|
|
working_directory = $BaseDir
|
|
}
|
|
checks_performed = @(
|
|
"environment_validation",
|
|
"integration_tests",
|
|
"workflow_validation_tests",
|
|
"health_monitoring",
|
|
"advanced_validation",
|
|
"dependency_validation",
|
|
"performance_monitoring"
|
|
)
|
|
artifacts = @(
|
|
"integration-tests.log",
|
|
"workflow-tests.log",
|
|
"health-check.log",
|
|
"advanced-validation.log",
|
|
"dependency-validation.log",
|
|
"performance-monitor.log",
|
|
"npm-install.log"
|
|
)
|
|
workspace = $workspace
|
|
}
|
|
$report | ConvertTo-Json -Depth 10 | Out-File -FilePath $reportFile
|
|
|
|
Write-CILog "INFO" "CI pipeline report saved to: $reportFile"
|
|
Write-CILog "INFO" "CI artifacts saved to: $workspace"
|
|
Write-CILog "INFO" "Pipeline duration: $([int]$duration)s"
|
|
|
|
if ($exitCode -eq 0) {
|
|
Write-CILog "PASS" "CI pipeline completed successfully"
|
|
} else {
|
|
Write-CILog "FAIL" "CI pipeline failed"
|
|
}
|
|
|
|
return $exitCode
|
|
}
|
|
|
|
# Install Git hooks
|
|
function Install-GitHooks {
|
|
Write-CILog "INFO" "Installing Git hooks..."
|
|
|
|
$hooksDir = Join-Path $BaseDir ".git\hooks"
|
|
$agentsHooksDir = Join-Path $AgentsDir "scripts\git-hooks"
|
|
|
|
# Create git-hooks directory
|
|
if (-not (Test-Path $agentsHooksDir)) {
|
|
New-Item -ItemType Directory -Path $agentsHooksDir -Force | Out-Null
|
|
}
|
|
|
|
# Create pre-commit hook
|
|
$preCommitContent = @'
|
|
#!/bin/bash
|
|
# Pre-commit hook for .agents validation
|
|
echo "Running .agents pre-commit validation..."
|
|
if bash .agents/scripts/ci-hooks.sh pre-commit; then
|
|
echo "Pre-commit validation passed"
|
|
exit 0
|
|
else
|
|
echo "Pre-commit validation failed"
|
|
exit 1
|
|
fi
|
|
'@
|
|
$preCommitContent | Out-File -FilePath (Join-Path $agentsHooksDir "pre-commit") -Encoding UTF8
|
|
|
|
# Create pre-push hook
|
|
$prePushContent = @'
|
|
#!/bin/bash
|
|
# Pre-push hook for .agents validation
|
|
echo "Running .agents pre-push validation..."
|
|
if bash .agents/scripts/ci-hooks.sh pre-push; then
|
|
echo "Pre-push validation passed"
|
|
exit 0
|
|
else
|
|
echo "Pre-push validation failed"
|
|
exit 1
|
|
fi
|
|
'@
|
|
$prePushContent | Out-File -FilePath (Join-Path $agentsHooksDir "pre-push") -Encoding UTF8
|
|
|
|
# Install hooks if .git directory exists
|
|
if (Test-Path $hooksDir) {
|
|
Copy-Item (Join-Path $agentsHooksDir "pre-commit") $hooksDir -Force
|
|
Copy-Item (Join-Path $agentsHooksDir "pre-push") $hooksDir -Force
|
|
Write-CILog "PASS" "Git hooks installed successfully"
|
|
} else {
|
|
Write-CILog "WARN" "Git repository not found, hooks copied to .agents\scripts\git-hooks"
|
|
}
|
|
}
|
|
|
|
# Main execution
|
|
switch ($Command) {
|
|
"pre-commit" {
|
|
exit (Invoke-PreCommitHook)
|
|
}
|
|
"pre-push" {
|
|
exit (Invoke-PrePushHook)
|
|
}
|
|
"ci-pipeline" {
|
|
exit (Invoke-CIPipelineHook)
|
|
}
|
|
"install-hooks" {
|
|
Install-GitHooks
|
|
}
|
|
"help" {
|
|
Write-Host "Usage: .\ci-hooks.ps1 -Command {pre-commit|pre-push|ci-pipeline|install-hooks|help}"
|
|
Write-Host ""
|
|
Write-Host "Commands:"
|
|
Write-Host " pre-commit - Run pre-commit validation"
|
|
Write-Host " pre-push - Run pre-push validation"
|
|
Write-Host " ci-pipeline - Run full CI pipeline"
|
|
Write-Host " install-hooks - Install Git hooks"
|
|
Write-Host " help - Show this help"
|
|
}
|
|
default {
|
|
Write-Host "Unknown command: $Command"
|
|
Write-Host "Use 'help' to see available commands"
|
|
exit 1
|
|
}
|
|
}
|