param( [switch]$WithDatabase, [switch]$SkipBuild ) $ErrorActionPreference = 'Stop' $projectRoot = Split-Path -Parent $PSScriptRoot Push-Location $projectRoot try { $phpFiles = Get-ChildItem backend -Recurse -Filter *.php -File foreach ($file in $phpFiles) { & php -l $file.FullName | Out-Null if ($LASTEXITCODE -ne 0) { throw "PHP lint failed: $($file.FullName)" } } Write-Host "PASS PHP lint ($($phpFiles.Count) files)" & php backend/tests/run.php if ($LASTEXITCODE -ne 0) { throw 'Backend unit tests failed.' } Push-Location frontend try { & npm.cmd test if ($LASTEXITCODE -ne 0) { throw 'Frontend tests failed.' } & npx.cmd eslint . --quiet if ($LASTEXITCODE -ne 0) { throw 'ESLint failed.' } if (-not $SkipBuild) { & npm.cmd run build if ($LASTEXITCODE -ne 0) { throw 'Production build failed.' } } } finally { Pop-Location } if ($WithDatabase) { if (-not $env:TEST_DB_NAME -or $env:TEST_DB_NAME -notmatch '_test$') { throw 'Set TEST_DB_NAME to a database ending in _test before using -WithDatabase.' } & php backend/tests/database.php if ($LASTEXITCODE -ne 0) { throw 'Database integration tests failed.' } & node backend/tests/http-smoke.mjs if ($LASTEXITCODE -ne 0) { throw 'HTTP smoke tests failed.' } } Write-Host 'QUALITY GATE PASSED' } finally { Pop-Location }