# 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 } }