Files
git.stella-ops.org/devops/scripts/local-ci.ps1

265 lines
7.0 KiB
PowerShell

<#
.SYNOPSIS
Local CI Runner for Windows
PowerShell wrapper for local-ci.sh
.DESCRIPTION
Unified local CI/CD testing runner for StellaOps on Windows.
This script wraps the Bash implementation via WSL2 or Git Bash.
.PARAMETER Mode
The testing mode to run:
- smoke : Quick smoke test (unit tests only, ~2 min)
- pr : Full PR-gating suite (all required checks, ~15 min)
- module : Module-specific tests (auto-detect or specified)
- workflow : Simulate specific workflow via act
- release : Release simulation (dry-run)
- full : All tests including extended categories (~45 min)
.PARAMETER Category
Specific test category to run (Unit, Architecture, Contract, Integration, Security, Golden)
.PARAMETER Module
Specific module to test (Scanner, Concelier, Authority, etc.)
.PARAMETER Workflow
Specific workflow to simulate (for workflow mode)
.PARAMETER Docker
Force Docker execution mode
.PARAMETER Native
Force native execution mode
.PARAMETER Act
Force act execution mode
.PARAMETER Parallel
Number of parallel test runners (default: auto-detect)
.PARAMETER Verbose
Enable verbose output
.PARAMETER DryRun
Show what would run without executing
.PARAMETER Rebuild
Force rebuild of CI Docker image
.PARAMETER NoServices
Skip starting CI services
.PARAMETER KeepServices
Don't stop services after tests
.EXAMPLE
.\local-ci.ps1 smoke
Quick validation before push
.EXAMPLE
.\local-ci.ps1 pr
Full PR check
.EXAMPLE
.\local-ci.ps1 module -Module Scanner
Test specific module
.EXAMPLE
.\local-ci.ps1 workflow -Workflow test-matrix
Simulate specific workflow
.NOTES
Requires WSL2 or Git Bash to execute the underlying Bash script.
For full feature support, use WSL2 with Ubuntu.
#>
[CmdletBinding()]
param(
[Parameter(Position = 0)]
[ValidateSet('smoke', 'pr', 'module', 'workflow', 'release', 'full')]
[string]$Mode = 'smoke',
[string]$Category,
[string]$Module,
[string]$Workflow,
[switch]$Docker,
[switch]$Native,
[switch]$Act,
[int]$Parallel,
[switch]$Verbose,
[switch]$DryRun,
[switch]$Rebuild,
[switch]$NoServices,
[switch]$KeepServices,
[switch]$Help
)
# Script location
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$RepoRoot = Split-Path -Parent (Split-Path -Parent $ScriptDir)
# Show help if requested
if ($Help) {
Get-Help $MyInvocation.MyCommand.Path -Detailed
exit 0
}
function Write-ColoredOutput {
param(
[string]$Message,
[ConsoleColor]$Color = [ConsoleColor]::White
)
$originalColor = $Host.UI.RawUI.ForegroundColor
$Host.UI.RawUI.ForegroundColor = $Color
Write-Host $Message
$Host.UI.RawUI.ForegroundColor = $originalColor
}
function Write-Info { Write-ColoredOutput "[INFO] $args" -Color Cyan }
function Write-Success { Write-ColoredOutput "[OK] $args" -Color Green }
function Write-Warning { Write-ColoredOutput "[WARN] $args" -Color Yellow }
function Write-Error { Write-ColoredOutput "[ERROR] $args" -Color Red }
# Find Bash executable
function Find-BashExecutable {
# Priority: WSL2 > Git Bash > Windows Subsystem for Linux (legacy)
# Check for WSL
$wsl = Get-Command wsl -ErrorAction SilentlyContinue
if ($wsl) {
# Verify WSL is working
$wslCheck = & wsl --status 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Info "Using WSL2 for Bash execution"
return @{ Type = 'wsl'; Path = 'wsl' }
}
}
# Check for Git Bash
$gitBashPaths = @(
"C:\Program Files\Git\bin\bash.exe",
"C:\Program Files (x86)\Git\bin\bash.exe",
"$env:LOCALAPPDATA\Programs\Git\bin\bash.exe"
)
foreach ($path in $gitBashPaths) {
if (Test-Path $path) {
Write-Info "Using Git Bash for execution"
return @{ Type = 'gitbash'; Path = $path }
}
}
# Check PATH for bash
$bashInPath = Get-Command bash -ErrorAction SilentlyContinue
if ($bashInPath) {
Write-Info "Using Bash from PATH"
return @{ Type = 'path'; Path = $bashInPath.Source }
}
return $null
}
# Convert Windows path to Unix path for WSL
function Convert-ToUnixPath {
param([string]$WindowsPath)
if ($WindowsPath -match '^([A-Za-z]):(.*)$') {
$drive = $Matches[1].ToLower()
$rest = $Matches[2] -replace '\\', '/'
return "/mnt/$drive$rest"
}
return $WindowsPath -replace '\\', '/'
}
# Build argument list
function Build-Arguments {
$args = @($Mode)
if ($Category) { $args += "--category"; $args += $Category }
if ($Module) { $args += "--module"; $args += $Module }
if ($Workflow) { $args += "--workflow"; $args += $Workflow }
if ($Docker) { $args += "--docker" }
if ($Native) { $args += "--native" }
if ($Act) { $args += "--act" }
if ($Parallel) { $args += "--parallel"; $args += $Parallel }
if ($Verbose) { $args += "--verbose" }
if ($DryRun) { $args += "--dry-run" }
if ($Rebuild) { $args += "--rebuild" }
if ($NoServices) { $args += "--no-services" }
if ($KeepServices) { $args += "--keep-services" }
return $args
}
# Main execution
Write-Host ""
Write-Host "=========================================" -ForegroundColor Magenta
Write-Host " StellaOps Local CI Runner (Windows) " -ForegroundColor Magenta
Write-Host "=========================================" -ForegroundColor Magenta
Write-Host ""
# Find Bash
$bash = Find-BashExecutable
if (-not $bash) {
Write-Error "Bash not found. Please install one of the following:"
Write-Host " - WSL2: https://docs.microsoft.com/en-us/windows/wsl/install"
Write-Host " - Git for Windows: https://git-scm.com/download/win"
exit 1
}
# Build script path
$scriptPath = Join-Path $ScriptDir "local-ci.sh"
if (-not (Test-Path $scriptPath)) {
Write-Error "Script not found: $scriptPath"
exit 1
}
# Build arguments
$bashArgs = Build-Arguments
Write-Info "Mode: $Mode"
Write-Info "Bash: $($bash.Type)"
Write-Info "Repository: $RepoRoot"
Write-Host ""
# Execute based on Bash type
try {
switch ($bash.Type) {
'wsl' {
$unixScript = Convert-ToUnixPath $scriptPath
Write-Info "Executing: wsl bash $unixScript $($bashArgs -join ' ')"
& wsl bash $unixScript @bashArgs
}
'gitbash' {
# Git Bash uses its own path conversion
$unixScript = $scriptPath -replace '\\', '/'
Write-Info "Executing: $($bash.Path) $unixScript $($bashArgs -join ' ')"
& $bash.Path $unixScript @bashArgs
}
'path' {
Write-Info "Executing: bash $scriptPath $($bashArgs -join ' ')"
& bash $scriptPath @bashArgs
}
}
$exitCode = $LASTEXITCODE
}
catch {
Write-Error "Execution failed: $_"
$exitCode = 1
}
# Report result
Write-Host ""
if ($exitCode -eq 0) {
Write-Success "Local CI completed successfully!"
} else {
Write-Error "Local CI failed with exit code: $exitCode"
}
exit $exitCode