Files
VibeFinance/test.ps1
T
Jordy HoogeveenandClaude Opus 5 50ed671e97 Release-script controleert registry-login en origin vóór de build
De release strandde pas na een volledige multi-arch build op
"401 Unauthorized" van de registry, en bleef daarvoor minuten hangen op een
SSH-wachtwoordprompt bij de tag-controle. Beide checks staan nu vooraan.

- Stap 1 heet nu "Controles (tags + registry-login)" en test achtereenvolgens:
  bestaat de tag al lokaal, is origin bereikbaar, bestaat de tag al op origin,
  bestaat het image al, en is er een geldige registry-login
- Registry-login: wanneer REGISTRY_USER en REGISTRY_TOKEN (of GITEA_TOKEN)
  gezet zijn logt het script zelf in via --password-stdin, anders stopt het met
  instructies. dev.ps1 push doet dezelfde controle
- Git draait met GIT_SSH_COMMAND="ssh -o BatchMode=yes -o ConnectTimeout=10",
  dus geen hangende prompts meer; bij geen toegang een uitleg met het
  https-alternatief
- Scripts eindigen expliciet met exit 0 (anders lekt de exitcode van het
  laatste docker-commando door), en een -DryRun meldt in de slotregel dat er
  niets is gepubliceerd
- BEHEER.md: registry-login met token en de REGISTRY_USER/REGISTRY_TOKEN route

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-04 22:47:48 +02:00

176 lines
7.2 KiB
PowerShell

# ── VibeFinance testscript (PowerShell) ──────────────────────────────────
# Draait de volledige testsuite voor de 2-container opzet. Alles gebeurt in
# Docker, dus je hebt geen Node op de host nodig.
#
# 1. Dependency-check (staan package.json's op de laatste versies?)
# 2. Backend-tests (Dockerfile target 'test' → node --test, zonder database)
# 3. Productiebuild (Vite-build + app-image; faalt de frontend, faalt dit)
# 4. Smoketest (productie-image + postgres, /api/health en / opvragen)
#
# De smoketest publiceert geen hostpoorten en gebruikt een eigen netwerk, dus
# hij botst niet met een draaiende dev-stack.
#
# Gebruik:
# .\test.ps1 # alle stappen
# .\test.ps1 -Unit # dependency-check + backend-tests
# .\test.ps1 -NoSmoke # zonder de stack te starten
# .\test.ps1 -Strict # faal als een dependency achterloopt
# .\test.ps1 -SkipDeps # dependency-check overslaan (bijv. offline)
param(
[switch]$Unit,
[switch]$NoSmoke,
[switch]$Strict,
[switch]$SkipDeps
)
$ErrorActionPreference = "Stop"
$appVersion = (Get-Content (Join-Path $PSScriptRoot "package.json") -Raw | ConvertFrom-Json).version
$testImage = "vibefinance/app:test-$appVersion"
$prodImage = "vibefinance/app:build-$appVersion"
$smokeNet = "vibefinance-smoke-net"
$smokeDb = "vibefinance-smoke-db"
$smokeApp = "vibefinance-smoke-app"
function Write-Step {
param([string]$Label)
Write-Host ""
Write-Host "── $Label" -ForegroundColor Cyan
}
# ── 1. Dependency-check ───────────────────────────────────────────────────
# Vergelijkt de versies in frontend/ en backend/package.json met het
# npm-register. Bewuste uitzonderingen staan in docker/update-exceptions.json.
if (-not $SkipDeps) {
Write-Step "[1/4] Dependency-check"
$checkArgs = @("node", "docker/check-updates.mjs")
if ($Strict) { $checkArgs += "--strict" }
docker run --rm -v "${PSScriptRoot}:/repo" -w /repo node:22-alpine @checkArgs
$checkCode = $LASTEXITCODE
if ($checkCode -ne 0) {
if ($Strict) {
Write-Error "Dependencies lopen achter — bijwerken of -SkipDeps gebruiken."
exit 1
}
Write-Host "Let op: er zijn nieuwere versies beschikbaar (zie hierboven)." -ForegroundColor Yellow
}
} else {
Write-Step "[1/4] Dependency-check overgeslagen (-SkipDeps)"
}
# ── 2. Backend-tests ──────────────────────────────────────────────────────
Write-Step "[2/4] Backend-tests"
docker build --target test -t $testImage $PSScriptRoot
if ($LASTEXITCODE -ne 0) { Write-Error "Testimage bouwen mislukt"; exit 1 }
docker run --rm $testImage
if ($LASTEXITCODE -ne 0) { Write-Error "Backend-tests mislukt"; exit 1 }
Write-Host "Backend-tests geslaagd" -ForegroundColor Green
if ($Unit) {
Write-Host ""
Write-Host "Alleen unit-tests gevraagd — klaar." -ForegroundColor Green
exit 0
}
# ── 3. Productiebuild (inclusief Vite-build) ──────────────────────────────
Write-Step "[3/4] Productie-image bouwen"
docker build --target production `
--build-arg APP_VERSION=$appVersion `
--build-arg VITE_APP_VERSION=$appVersion `
--build-arg VITE_API_URL=/api `
-t $prodImage $PSScriptRoot
if ($LASTEXITCODE -ne 0) { Write-Error "Productiebuild mislukt"; exit 1 }
Write-Host "Productie-image gebouwd: $prodImage" -ForegroundColor Green
if ($NoSmoke) {
Write-Host ""
Write-Host "Smoketest overgeslagen (-NoSmoke) — klaar." -ForegroundColor Green
exit 0
}
# ── 4. Smoketest op het productie-image + postgres ────────────────────────
Write-Step "[4/4] Smoketest (app + postgres)"
function Remove-SmokeStack {
docker rm -f $smokeApp $smokeDb 2>$null | Out-Null
docker network rm $smokeNet 2>$null | Out-Null
}
# Eventuele resten van een eerdere run opruimen
Remove-SmokeStack
try {
docker network create $smokeNet | Out-Null
docker run -d --name $smokeDb --network $smokeNet `
-e POSTGRES_DB=vibefinance `
-e POSTGRES_USER=vibefinance `
-e POSTGRES_PASSWORD=smokepassword `
postgres:18-alpine | Out-Null
if ($LASTEXITCODE -ne 0) { throw "Database-container starten mislukt" }
Write-Host " Wachten op postgres..." -ForegroundColor DarkGray
$dbGereed = $false
foreach ($poging in 1..30) {
docker exec $smokeDb pg_isready -U vibefinance 2>$null | Out-Null
if ($LASTEXITCODE -eq 0) { $dbGereed = $true; break }
Start-Sleep -Seconds 2
}
if (-not $dbGereed) { throw "Postgres werd niet bereikbaar" }
docker run -d --name $smokeApp --network $smokeNet `
-e NODE_ENV=production `
-e JWT_SECRET=smoke-secret `
-e UPDATE_CHECK_URL= `
-e DATABASE_URL=postgresql://vibefinance:smokepassword@$smokeDb`:5432/vibefinance `
$prodImage | Out-Null
if ($LASTEXITCODE -ne 0) { throw "App-container starten mislukt" }
Write-Host " Wachten op de app..." -ForegroundColor DarkGray
$health = $null
foreach ($poging in 1..30) {
$health = (docker exec $smokeApp wget -qO- http://127.0.0.1:3001/api/health 2>$null) -join ""
if ($LASTEXITCODE -eq 0 -and $health -match '"status"') { break }
$health = $null
Start-Sleep -Seconds 2
}
if (-not $health) {
docker logs --tail 40 $smokeApp
throw "App werd niet gezond"
}
Write-Host " /api/health : ok" -ForegroundColor Green
# wget levert meerdere regels; samenvoegen tot één string, want -match op een
# array filtert de array in plaats van een test te doen.
$index = (docker exec $smokeApp wget -qO- http://127.0.0.1:3001/) -join "`n"
if ($LASTEXITCODE -ne 0 -or $index -notmatch 'id="root"') { throw "Root gaf geen index.html terug" }
Write-Host " / : index.html" -ForegroundColor Green
$spa = (docker exec $smokeApp wget -qO- http://127.0.0.1:3001/voortgang) -join "`n"
if ($LASTEXITCODE -ne 0 -or $spa -notmatch 'id="root"') { throw "SPA-fallback werkt niet" }
Write-Host " /voortgang : index.html (SPA-fallback)" -ForegroundColor Green
$api404 = (docker exec $smokeApp wget -qO- --server-response http://127.0.0.1:3001/api/bestaat-niet 2>&1) -join "`n"
if ($api404 -notmatch "404") { throw "Onbekende API-route gaf geen 404" }
Write-Host " /api/bestaat-niet: 404" -ForegroundColor Green
Write-Host ""
Write-Host "Smoketest geslaagd" -ForegroundColor Green
}
finally {
Remove-SmokeStack
}
Write-Host ""
Write-Host "════════════════════════════════════════" -ForegroundColor Cyan
Write-Host " Alle tests geslaagd - $appVersion" -ForegroundColor Green
Write-Host "════════════════════════════════════════" -ForegroundColor Cyan
Write-Host ""
# Expliciete 0: zie release.ps1 — voorkomt een geërfde exitcode.
exit 0