2026-04-16 13:32:32 +02:00
|
|
|
|
# release.ps1 – Verbindlicher Single-Entry-Point fuer den lokalen AZA Release-Build
|
|
|
|
|
|
#
|
|
|
|
|
|
# Reihenfolge:
|
|
|
|
|
|
# 1. build_exe.ps1 (PyInstaller + Pre-Build-Validierung)
|
|
|
|
|
|
# 2. build_installer.ps1 (Inno Setup Installer)
|
|
|
|
|
|
# 3. build_release_manifest.ps1 (version.json aus aza_version.py)
|
|
|
|
|
|
# 4. Post-Build-Verifizierung
|
|
|
|
|
|
# 5. Abschlussmeldung mit Upload-Befehlen
|
|
|
|
|
|
#
|
|
|
|
|
|
# Verbindliche Release-Artefakte:
|
|
|
|
|
|
# dist\installer\aza_desktop_setup.exe
|
|
|
|
|
|
# release\version.json
|
|
|
|
|
|
|
|
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
|
|
$projectRoot = $PSScriptRoot
|
|
|
|
|
|
|
|
|
|
|
|
Write-Host ""
|
|
|
|
|
|
Write-Host "=============================================="
|
|
|
|
|
|
Write-Host " AZA Release-Build"
|
|
|
|
|
|
Write-Host "=============================================="
|
|
|
|
|
|
Write-Host ""
|
|
|
|
|
|
|
|
|
|
|
|
# --- Schritt 1: Desktop EXE bauen ---
|
|
|
|
|
|
Write-Host "[1/4] Desktop EXE bauen (build_exe.ps1)..."
|
|
|
|
|
|
Write-Host ""
|
|
|
|
|
|
& (Join-Path $projectRoot "build_exe.ps1")
|
|
|
|
|
|
if ($LASTEXITCODE -ne 0) {
|
|
|
|
|
|
Write-Error "ABBRUCH: build_exe.ps1 fehlgeschlagen."
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
}
|
|
|
|
|
|
Write-Host ""
|
|
|
|
|
|
|
|
|
|
|
|
# --- Schritt 2: Installer bauen ---
|
|
|
|
|
|
Write-Host "[2/4] Installer bauen (build_installer.ps1)..."
|
|
|
|
|
|
Write-Host ""
|
|
|
|
|
|
& (Join-Path $projectRoot "build_installer.ps1")
|
|
|
|
|
|
if ($LASTEXITCODE -ne 0) {
|
|
|
|
|
|
Write-Error "ABBRUCH: build_installer.ps1 fehlgeschlagen."
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
}
|
|
|
|
|
|
Write-Host ""
|
|
|
|
|
|
|
|
|
|
|
|
# --- Schritt 3: Release-Manifest aktualisieren ---
|
|
|
|
|
|
Write-Host "[3/4] Release-Manifest aktualisieren (build_release_manifest.ps1)..."
|
|
|
|
|
|
Write-Host ""
|
|
|
|
|
|
& (Join-Path $projectRoot "build_release_manifest.ps1")
|
|
|
|
|
|
if ($LASTEXITCODE -ne 0) {
|
|
|
|
|
|
Write-Error "ABBRUCH: build_release_manifest.ps1 fehlgeschlagen."
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
}
|
|
|
|
|
|
Write-Host ""
|
|
|
|
|
|
|
|
|
|
|
|
# --- Schritt 4: Post-Build-Verifizierung ---
|
|
|
|
|
|
Write-Host "[4/4] Post-Build-Verifizierung..."
|
|
|
|
|
|
Write-Host ""
|
|
|
|
|
|
|
|
|
|
|
|
$internalDir = Join-Path $projectRoot "dist\aza_desktop\_internal"
|
|
|
|
|
|
$installerPath = Join-Path $projectRoot "dist\installer\aza_desktop_setup.exe"
|
|
|
|
|
|
$manifestPath = Join-Path $projectRoot "release\version.json"
|
|
|
|
|
|
$errors = @()
|
|
|
|
|
|
|
|
|
|
|
|
# 4a) backend_url.txt pruefen
|
|
|
|
|
|
$urlFile = Join-Path $internalDir "backend_url.txt"
|
|
|
|
|
|
if (-not (Test-Path $urlFile)) {
|
|
|
|
|
|
$errors += "backend_url.txt fehlt in _internal"
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$urlContent = (Get-Content $urlFile -Raw).Trim()
|
|
|
|
|
|
if (-not $urlContent) {
|
|
|
|
|
|
$errors += "backend_url.txt in _internal ist leer"
|
|
|
|
|
|
} elseif ($urlContent -match "127\.0\.0\.1|localhost|0\.0\.0\.0") {
|
|
|
|
|
|
$errors += "backend_url.txt in _internal enthaelt lokale Adresse: $urlContent"
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Write-Host " backend_url.txt OK: $urlContent"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 4b) backend_token.txt pruefen
|
|
|
|
|
|
$tokenFile = Join-Path $internalDir "backend_token.txt"
|
|
|
|
|
|
if (-not (Test-Path $tokenFile)) {
|
|
|
|
|
|
$errors += "backend_token.txt fehlt in _internal"
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$tokenContent = (Get-Content $tokenFile -Raw).Trim()
|
|
|
|
|
|
if (-not $tokenContent) {
|
|
|
|
|
|
$errors += "backend_token.txt in _internal ist leer"
|
|
|
|
|
|
} elseif ($tokenContent -match "CHANGE_ME") {
|
|
|
|
|
|
$errors += "backend_token.txt in _internal enthaelt Platzhalter"
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Write-Host " backend_token.txt OK (Token vorhanden)"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 4c) Verbotene Dateien duerfen NICHT in _internal liegen
|
|
|
|
|
|
$forbidden = @(".env", "license_url.txt")
|
|
|
|
|
|
foreach ($f in $forbidden) {
|
|
|
|
|
|
$fp = Join-Path $internalDir $f
|
|
|
|
|
|
if (Test-Path $fp) {
|
|
|
|
|
|
$errors += "VERBOTEN: $f liegt in _internal (darf nicht im Installer sein)"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
$forbiddenDb = Join-Path $internalDir "data\stripe_webhook.sqlite"
|
|
|
|
|
|
if (Test-Path $forbiddenDb) {
|
|
|
|
|
|
$errors += "VERBOTEN: data\stripe_webhook.sqlite liegt in _internal (darf nicht im Installer sein)"
|
|
|
|
|
|
}
|
|
|
|
|
|
if ($errors.Count -eq 0) {
|
|
|
|
|
|
Write-Host " Keine verbotenen Dateien in _internal"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-16 20:33:36 +02:00
|
|
|
|
# 4f) Empfang-Web-Huelle: PyInstaller-Ausgabe und Kopie neben aza_desktop muessen identisch sein
|
|
|
|
|
|
$shellExeRoot = Join-Path $projectRoot "dist\AZA_EmpfangShell.exe"
|
2026-05-11 08:27:44 +02:00
|
|
|
|
$shellExeDist = Join-Path $projectRoot "dist\aza_desktop\AZA_EmpfangShell.exe"
|
2026-05-16 20:33:36 +02:00
|
|
|
|
if (-not (Test-Path $shellExeRoot)) {
|
|
|
|
|
|
$errors += "AZA_EmpfangShell.exe fehlt in dist\ (PyInstaller-Ausgabe) - build_exe.ps1 pruefen"
|
|
|
|
|
|
} elseif (-not (Test-Path $shellExeDist)) {
|
|
|
|
|
|
$errors += "AZA_EmpfangShell.exe fehlt in dist\aza_desktop\ - build_exe.ps1 muss die Shell kopieren"
|
2026-05-11 08:27:44 +02:00
|
|
|
|
} else {
|
2026-05-16 20:33:36 +02:00
|
|
|
|
$tRoot = (Get-Item $shellExeRoot).LastWriteTime
|
|
|
|
|
|
$tDesk = (Get-Item $shellExeDist).LastWriteTime
|
|
|
|
|
|
$hRoot = (Get-FileHash -Path $shellExeRoot -Algorithm SHA256).Hash
|
|
|
|
|
|
$hDesk = (Get-FileHash -Path $shellExeDist -Algorithm SHA256).Hash
|
|
|
|
|
|
Write-Host (" AZA_EmpfangShell.exe dist\: Zeit {0:yyyy-MM-dd HH:mm:ss}, SHA256={1}" -f $tRoot, $hRoot)
|
|
|
|
|
|
Write-Host (" AZA_EmpfangShell.exe desktop\: Zeit {0:yyyy-MM-dd HH:mm:ss}, SHA256={1}" -f $tDesk, $hDesk)
|
|
|
|
|
|
if ($hRoot -ne $hDesk) {
|
|
|
|
|
|
$errors += "AZA_EmpfangShell.exe: SHA256-Unterschied zwischen dist\ und dist\aza_desktop\ - Build inkonsistent"
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Write-Host " AZA_EmpfangShell.exe: dist\ und dist\aza_desktop\ identisch OK"
|
|
|
|
|
|
}
|
2026-05-11 08:27:44 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-16 13:32:32 +02:00
|
|
|
|
# 4d) Installer existiert und hat Groesse > 0
|
|
|
|
|
|
if (-not (Test-Path $installerPath)) {
|
|
|
|
|
|
$errors += "Installer nicht gefunden: $installerPath"
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$fileInfo = Get-Item $installerPath
|
|
|
|
|
|
if ($fileInfo.Length -eq 0) {
|
|
|
|
|
|
$errors += "Installer hat Groesse 0: $installerPath"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 4e) version.json existiert und Version stimmt mit aza_version.py ueberein
|
|
|
|
|
|
if (-not (Test-Path $manifestPath)) {
|
|
|
|
|
|
$errors += "release\version.json nicht gefunden"
|
|
|
|
|
|
} else {
|
|
|
|
|
|
try {
|
|
|
|
|
|
$manifest = Get-Content $manifestPath -Raw | ConvertFrom-Json
|
|
|
|
|
|
$manifestVersion = $manifest.version
|
|
|
|
|
|
$azaContent = Get-Content (Join-Path $projectRoot "aza_version.py") -Raw
|
|
|
|
|
|
if ($azaContent -match 'APP_VERSION\s*=\s*"([^"]+)"') {
|
|
|
|
|
|
$codeVersion = $matches[1].Trim()
|
|
|
|
|
|
if ($manifestVersion -ne $codeVersion) {
|
|
|
|
|
|
$errors += "version.json Version ($manifestVersion) stimmt nicht mit aza_version.py ($codeVersion) ueberein"
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Write-Host " version.json OK: Version $manifestVersion"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
$dlUrl = $manifest.download_url
|
|
|
|
|
|
if ($dlUrl -and ($dlUrl -match "127\.0\.0\.1|localhost")) {
|
|
|
|
|
|
$errors += "version.json download_url enthaelt localhost: $dlUrl"
|
|
|
|
|
|
}
|
2026-05-16 20:33:36 +02:00
|
|
|
|
$mfSha = $manifest.sha256
|
|
|
|
|
|
if ($mfSha -and (Test-Path $installerPath)) {
|
|
|
|
|
|
$instSha = (Get-FileHash -Path $installerPath -Algorithm SHA256).Hash
|
|
|
|
|
|
$mfShaNorm = $mfSha.ToString().Trim()
|
|
|
|
|
|
if ($mfShaNorm -and ($mfShaNorm -ne $instSha)) {
|
|
|
|
|
|
$errors += "version.json sha256 stimmt nicht mit Installer ueberein (Manifest=$mfShaNorm Installer=$instSha)"
|
|
|
|
|
|
} elseif ($mfShaNorm) {
|
|
|
|
|
|
Write-Host " sha256 OK: Manifest und Installer identisch"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-04-16 13:32:32 +02:00
|
|
|
|
} catch {
|
|
|
|
|
|
$errors += "version.json konnte nicht gelesen werden: $_"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Fehler auswerten
|
|
|
|
|
|
if ($errors.Count -gt 0) {
|
|
|
|
|
|
Write-Host ""
|
|
|
|
|
|
Write-Host "=============================================="
|
|
|
|
|
|
Write-Host " RELEASE-VERIFIZIERUNG FEHLGESCHLAGEN"
|
|
|
|
|
|
Write-Host "=============================================="
|
|
|
|
|
|
foreach ($e in $errors) {
|
|
|
|
|
|
Write-Host " FEHLER: $e" -ForegroundColor Red
|
|
|
|
|
|
}
|
|
|
|
|
|
Write-Host ""
|
|
|
|
|
|
Write-Error "Release-Build nicht sauber. Bitte Fehler beheben und erneut ausfuehren."
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# --- Abschlussmeldung ---
|
|
|
|
|
|
$instInfo = Get-Item $installerPath
|
|
|
|
|
|
$sizeMB = [math]::Round($instInfo.Length / 1MB, 2)
|
|
|
|
|
|
$sha256 = (Get-FileHash -Path $installerPath -Algorithm SHA256).Hash
|
|
|
|
|
|
|
2026-05-16 20:33:36 +02:00
|
|
|
|
$stamp = Get-Date -Format "yyyyMMdd_HHmmss"
|
|
|
|
|
|
$stampedInstaller = Join-Path $projectRoot "dist\installer\aza_desktop_setup_$stamp.exe"
|
|
|
|
|
|
try {
|
|
|
|
|
|
Copy-Item -LiteralPath $installerPath -Destination $stampedInstaller -Force
|
|
|
|
|
|
Write-Host " Zeitstempel-Kopie des Installers: $stampedInstaller"
|
|
|
|
|
|
} catch {
|
|
|
|
|
|
Write-Warning "Zeitstempel-Kopie konnte nicht erstellt werden: $_"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-16 13:32:32 +02:00
|
|
|
|
Write-Host ""
|
|
|
|
|
|
Write-Host "=============================================="
|
|
|
|
|
|
Write-Host " RELEASE BEREIT FUER UPLOAD"
|
|
|
|
|
|
Write-Host "=============================================="
|
|
|
|
|
|
Write-Host ""
|
|
|
|
|
|
Write-Host " Installer: $installerPath"
|
|
|
|
|
|
Write-Host " Groesse: $sizeMB MB"
|
|
|
|
|
|
Write-Host " SHA256: $sha256"
|
|
|
|
|
|
Write-Host " Manifest: $manifestPath"
|
|
|
|
|
|
Write-Host ""
|
2026-05-16 20:33:36 +02:00
|
|
|
|
Write-Host " Upload-Befehle (Produktion laut Vorgabe; ggf. andere IP in Staging-Umgebungen):"
|
|
|
|
|
|
Write-Host " scp `"$installerPath`" root@178.104.51.177:/root/aza-app/release/aza_desktop_setup.exe"
|
|
|
|
|
|
Write-Host " scp `"$manifestPath`" root@178.104.51.177:/root/aza-app/release/version.json"
|
2026-04-16 13:32:32 +02:00
|
|
|
|
Write-Host ""
|