param( [switch]$SkipDotnetRestore, [switch]$SkipBuild, [switch]$SkipPlaywright ) Set-StrictMode -Version Latest $ErrorActionPreference = "Stop" function Invoke-Step { param( [Parameter(Mandatory = $true)][string]$Name, [Parameter(Mandatory = $true)][scriptblock]$Action ) Write-Host "==> $Name" & $Action if ($LASTEXITCODE -ne 0) { throw "Step failed: $Name" } } $scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path $repoRoot = Split-Path -Parent $scriptDir Push-Location $repoRoot try { if (-not $SkipDotnetRestore) { Invoke-Step -Name "Restore .NET solution" -Action { dotnet restore RpgRoller.sln --verbosity minimal } } if (-not $SkipBuild) { Invoke-Step -Name "Build .NET solution (warnings as errors)" -Action { dotnet build RpgRoller.sln --no-restore -warnaserror --verbosity minimal } } Invoke-Step -Name "Restore Node dependencies" -Action { npm ci } Invoke-Step -Name "Ensure Playwright browser" -Action { npm exec playwright install chromium } Invoke-Step -Name "Run tests" -Action { if ($SkipBuild) { dotnet test RpgRoller.Tests/RpgRoller.Tests.csproj --verbosity minimal --collect:"XPlat Code Coverage" --settings RpgRoller.Tests/coverlet.runsettings } else { dotnet test RpgRoller.Tests/RpgRoller.Tests.csproj --no-build --verbosity minimal --collect:"XPlat Code Coverage" --settings RpgRoller.Tests/coverlet.runsettings } } Invoke-Step -Name "Enforce coverage thresholds" -Action { pwsh ./scripts/check-coverage.ps1 -MinLineRate 0.90 -MinBranchRate 0.70 } if (-not $SkipPlaywright) { Invoke-Step -Name "Run Playwright smoke test" -Action { pwsh ./scripts/run-playwright.ps1 } } Write-Host "CI checks passed." } finally { Pop-Location }