<# .SYNOPSIS QR-Code-Generator aktualisieren: neuen Stand holen, Stack neu bauen, starten. .DESCRIPTION Windows-Gegenstück zu update.sh. Holt den aktuellen Stand aus dem Git-Remote und baut den Docker-Stack neu, wenn es Änderungen gab. .PARAMETER Force Auch dann neu bauen, wenn es keine neuen Commits gibt. .PARAMETER Prune Nach dem Bauen verwaiste Docker-Images entfernen. .EXAMPLE .\update.ps1 .\update.ps1 -Force -Prune #> [CmdletBinding()] param( [switch]$Force, [switch]$Prune ) $ErrorActionPreference = 'Stop' function Write-Info { param([string]$Text) Write-Host "→ $Text" } function Write-Ok { param([string]$Text) Write-Host "✓ $Text" -ForegroundColor Green } function Stop-WithError { param([string]$Text) Write-Host "✗ $Text" -ForegroundColor Red exit 1 } # Immer im Projektverzeichnis arbeiten, egal von wo das Skript gestartet wird. Set-Location -Path $PSScriptRoot # --- Voraussetzungen -------------------------------------------------------- foreach ($tool in @('git', 'docker')) { if (-not (Get-Command $tool -ErrorAction SilentlyContinue)) { Stop-WithError "$tool ist nicht installiert." } } docker compose version *> $null if (-not $?) { Stop-WithError 'docker compose ist nicht verfügbar (Docker Compose v2 wird benötigt).' } if (-not (Test-Path .env)) { Stop-WithError '.env fehlt. Anlegen mit: Copy-Item .env.example .env' } # Ein "git pull" auf einem veränderten Arbeitsverzeichnis endet im Konflikt. $dirty = git status --porcelain if ($dirty) { Write-Host '✗ Es gibt lokale Änderungen im Arbeitsverzeichnis:' -ForegroundColor Red git status --short Write-Host '' Stop-WithError "Bitte zuerst committen oder mit 'git stash' beiseitelegen." } # --- Neuen Stand holen ------------------------------------------------------ $before = git rev-parse HEAD $branch = git rev-parse --abbrev-ref HEAD Write-Info "Hole neuen Stand von origin/$branch …" git fetch --quiet origin if (-not $?) { Stop-WithError 'Der Remote ist nicht erreichbar.' } # --ff-only: lieber abbrechen als eine Merge-Situation erzeugen. git merge --ff-only --quiet "origin/$branch" if (-not $?) { Stop-WithError 'Der lokale Stand lässt sich nicht ohne Merge aktualisieren. Bitte von Hand prüfen.' } $after = git rev-parse HEAD if ($before -eq $after) { Write-Ok "Bereits auf dem neuesten Stand ($(git rev-parse --short HEAD))." } else { Write-Ok "Aktualisiert: $(git rev-parse --short $before) → $(git rev-parse --short $after)" Write-Host '' git --no-pager log --oneline "$before..$after" Write-Host '' } # --- Stack neu bauen -------------------------------------------------------- $running = @(docker compose ps --status running --quiet).Count if (($before -eq $after) -and (-not $Force) -and ($running -gt 0)) { Write-Ok 'Der Stack läuft und es gibt nichts Neues — kein Neubau nötig.' Write-Host ' (Mit .\update.ps1 -Force lässt sich ein Neubau erzwingen.)' exit 0 } Write-Info 'Baue und starte den Stack neu — das dauert einige Minuten …' docker compose up -d --build if (-not $?) { Stop-WithError 'Der Neubau ist fehlgeschlagen.' } # --- Warten, bis die Anwendung antwortet ------------------------------------ # Nur die Ziffern behalten — so stören weder Anführungszeichen noch Leerzeichen. $portLine = Select-String -Path .env -Pattern '^APP_PORT=' | Select-Object -First 1 $appPort = if ($portLine) { ($portLine.Line -replace '\D', '') } else { '' } if (-not $appPort) { $appPort = '3000' } Write-Info 'Warte darauf, dass die Anwendung antwortet …' $ready = $false for ($attempt = 0; $attempt -lt 60; $attempt++) { try { Invoke-WebRequest -Uri "http://localhost:$appPort/" -UseBasicParsing -TimeoutSec 5 | Out-Null $ready = $true break } catch { Start-Sleep -Seconds 2 } } if (-not $ready) { docker compose logs --tail 40 app Stop-WithError 'Die Anwendung antwortet nach 2 Minuten nicht. Protokoll siehe oben.' } Write-Ok "Die Anwendung antwortet auf http://localhost:$appPort" # --- Ergebnis --------------------------------------------------------------- Write-Host '' Write-Info 'Datenbankmigrationen beim Start:' docker compose logs app | Select-String -Pattern 'migration', 'Migration', 'pending' | Select-Object -Last 5 | ForEach-Object { " $($_.Line)" } Write-Host '' docker compose ps if ($Prune) { Write-Host '' Write-Info 'Räume verwaiste Docker-Images auf …' docker image prune --force } Write-Host '' Write-Ok "Fertig — Version $(git rev-parse --short HEAD)"