Build/Build-Module.ps1
|
<#
.SYNOPSIS Build and validate the iFacto.AICodeReview module .DESCRIPTION This script validates the module structure, runs tests, and checks the manifest. Use this before publishing to PowerShell Gallery. .PARAMETER SkipTests Skip running Pester tests .EXAMPLE .\Build-Module.ps1 .EXAMPLE .\Build-Module.ps1 -SkipTests #> [CmdletBinding()] param( [Parameter()] [switch]$SkipTests ) $ErrorActionPreference = 'Stop' # Get module root directory $moduleRoot = Split-Path $PSScriptRoot -Parent $moduleName = 'iFacto.AICodeReview' $manifestPath = Join-Path $moduleRoot "$moduleName.psd1" Write-Host "========================================" -ForegroundColor Cyan Write-Host " Building $moduleName Module" -ForegroundColor Cyan Write-Host "========================================" -ForegroundColor Cyan Write-Host "" # Step 1: Validate module structure Write-Host "✓ Validating module structure..." -ForegroundColor Yellow $requiredFolders = @('Public', 'Private', 'Rules', 'Tests', 'Examples') foreach ($folder in $requiredFolders) { $folderPath = Join-Path $moduleRoot $folder if (-not (Test-Path $folderPath)) { throw "Required folder missing: $folder" } Write-Host " ✓ $folder" -ForegroundColor Green } # Step 2: Validate manifest Write-Host "" Write-Host "✓ Validating module manifest..." -ForegroundColor Yellow try { $manifest = Test-ModuleManifest -Path $manifestPath -ErrorAction Stop Write-Host " ✓ Manifest valid" -ForegroundColor Green Write-Host " ✓ Version: $($manifest.Version)" -ForegroundColor Green Write-Host " ✓ Author: $($manifest.Author)" -ForegroundColor Green Write-Host " ✓ Functions: $($manifest.ExportedFunctions.Count)" -ForegroundColor Green } catch { throw "Module manifest validation failed: $_" } # Step 3: Check function exports match actual files Write-Host "" Write-Host "✓ Validating function exports..." -ForegroundColor Yellow $publicFunctions = Get-ChildItem -Path (Join-Path $moduleRoot 'Public') -Filter '*.ps1' | Select-Object -ExpandProperty BaseName $exportedFunctions = $manifest.ExportedFunctions.Keys foreach ($func in $publicFunctions) { if ($func -notin $exportedFunctions) { throw "Function '$func' exists in Public but not exported in manifest" } Write-Host " ✓ $func" -ForegroundColor Green } foreach ($func in $exportedFunctions) { if ($func -notin $publicFunctions) { throw "Function '$func' exported in manifest but file missing in Public" } } # Step 4: Run Pester tests if (-not $SkipTests) { Write-Host "" Write-Host "✓ Running Pester tests..." -ForegroundColor Yellow # Import Pester $pesterModule = Get-Module Pester -ListAvailable | Where-Object { $_.Version -ge '5.0' } | Select-Object -First 1 if (-not $pesterModule) { throw "Pester 5.x or higher is required. Install with: Install-Module Pester -Force -SkipPublisherCheck" } Import-Module Pester -MinimumVersion 5.0 -Force # Run tests $testsPath = Join-Path $moduleRoot 'Tests' $testResults = Invoke-Pester -Path $testsPath -PassThru if ($testResults.FailedCount -gt 0) { throw "Tests failed: $($testResults.FailedCount) test(s) failed" } Write-Host " ✓ All tests passed ($($testResults.PassedCount) tests)" -ForegroundColor Green } else { Write-Host "" Write-Host "⚠ Skipping tests" -ForegroundColor Yellow } # Step 5: Validate required files exist Write-Host "" Write-Host "✓ Validating required files..." -ForegroundColor Yellow $requiredFiles = @( 'README.md', 'LICENSE', 'CHANGELOG.md', 'Rules\core-rules.md', 'Rules\model-config.json' ) foreach ($file in $requiredFiles) { $filePath = Join-Path $moduleRoot $file if (-not (Test-Path $filePath)) { throw "Required file missing: $file" } Write-Host " ✓ $file" -ForegroundColor Green } # Step 6: Check for syntax errors in all .ps1 files Write-Host "" Write-Host "✓ Checking PowerShell syntax..." -ForegroundColor Yellow $psFiles = Get-ChildItem -Path $moduleRoot -Filter '*.ps1' -Recurse -Exclude '*.Tests.ps1' $syntaxErrors = @() foreach ($file in $psFiles) { $errors = $null [System.Management.Automation.PSParser]::Tokenize((Get-Content -Path $file.FullName -Raw), [ref]$errors) | Out-Null if ($errors.Count -gt 0) { $syntaxErrors += @{ File = $file.FullName Errors = $errors } } } if ($syntaxErrors.Count -gt 0) { Write-Host "" Write-Host "Syntax errors found:" -ForegroundColor Red foreach ($item in $syntaxErrors) { Write-Host " File: $($item.File)" -ForegroundColor Red foreach ($error in $item.Errors) { Write-Host " $error" -ForegroundColor Red } } throw "Syntax errors found in PowerShell files" } Write-Host " ✓ No syntax errors" -ForegroundColor Green # Success Write-Host "" Write-Host "========================================" -ForegroundColor Green Write-Host " ✓ Build Complete - Module is valid!" -ForegroundColor Green Write-Host "========================================" -ForegroundColor Green Write-Host "" Write-Host "Module is ready to publish:" -ForegroundColor Cyan Write-Host " Publish-Module -Path '$moduleRoot' -NuGetApiKey `$env:NUGET_API_KEY" -ForegroundColor White Write-Host "" |