#!/usr/bin/env bash # Baut die Windows-.exe mit Windows-Python unter Wine (z. B. im Container tobix/pywine:3.12). # Ergebnis: dist/Provisionsmanager95.exe, dist/Provisionsmanager95-.zip und # dist/Provisionsmanager-Setup-.exe (Inno Setup, Installation pro Benutzer) set -euo pipefail cd "$(dirname "$0")/.." export WINEDEBUG=-all export LANG=C.UTF-8 LC_ALL=C.UTF-8 # sonst kann Wine keine Umlaute in Dateinamen abbilden export WINEPREFIX="${WINEPREFIX:-/opt/wineprefix}" PY="wine python" # Ein virtueller Bildschirm für den GANZEN Build – vor dem ersten Wine-Aufruf starten! # Wine bindet seinen Hintergrundprozess (wineserver/Desktop) an das DISPLAY des ersten Aufrufs. # Läuft z. B. „pip install“ ohne Bildschirm und die GUI-Tests später mit, scheitert Tk unter # Wine mit „Failed to create the menu window“. wineserver -k 2>/dev/null || true ANZEIGE=":$((90 + RANDOM % 9))" Xvfb "$ANZEIGE" -screen 0 1280x800x24 -nolisten tcp >/dev/null 2>&1 & XVFB_PID=$! trap 'wineserver -k 2>/dev/null || true; kill $XVFB_PID 2>/dev/null || true' EXIT export DISPLAY="$ANZEIGE" sleep 1 $PY --version $PY -m pip install --disable-pip-version-check -q -r requirements-dev.txt echo "== Tests inkl. Oberfläche (Windows-Python unter Wine) ==" # PROVTOOL_GUI_TESTS=1: fehlt der Bildschirm, ist das ein Fehler (nicht „übersprungen“) # -v: im Log ist live sichtbar, welcher Test läuft; timeout: Obergrenze für alle Tests zusammen PROVTOOL_GUI_TESTS=1 timeout 900 $PY -m pytest -v -p no:cacheprovider echo "== Maustest (echte Maus: Fenster ziehen, Rand ziehen, maximiert ziehen) ==" PY="$PY" timeout 300 bash build/maustest.sh echo "== Version ==" VERSION=$($PY build/version_info.py | tr -d '\r') echo "Version $VERSION" echo "== PyInstaller ==" $PY -m PyInstaller --noconfirm --clean --distpath dist --workpath build/tmp build/provisionsmanager.spec test -f dist/Provisionsmanager95.exe test -f dist/Provisionsmanager/Provisionsmanager.exe # Ordner-Variante für das Setup selbsttest() { # $1 = zu prüfende .exe rm -f selbsttest.txt set +e timeout 300 wine "$1" --selbsttest selbsttest.txt CODE=$? set -e cat selbsttest.txt 2>/dev/null || echo "(keine Ergebnisdatei – die .exe ist vermutlich gar nicht gestartet)" if [ "$CODE" -ne 0 ] || ! head -1 selbsttest.txt 2>/dev/null | tr -d '\r' | grep -qx OK; then echo "Selbsttest von $1 FEHLGESCHLAGEN (Exit-Code $CODE)" exit 1 fi echo "Selbsttest bestanden" } echo "== Selbsttest der fertigen .exe ==" selbsttest dist/Provisionsmanager95.exe cp README.md dist/LIESMICH.md 2>/dev/null || true ( cd dist && rm -f Provisionsmanager95-*.zip && \ python3 -c "import zipfile,sys; z=zipfile.ZipFile(sys.argv[1],'w',zipfile.ZIP_DEFLATED); [z.write(f) for f in sys.argv[2:]]; z.close()" \ "Provisionsmanager95-${VERSION}.zip" Provisionsmanager95.exe LIESMICH.md 2>/dev/null \ || $PY -c "import zipfile,sys; z=zipfile.ZipFile(sys.argv[1],'w',zipfile.ZIP_DEFLATED); [z.write(f) for f in sys.argv[2:]]; z.close()" \ "Provisionsmanager95-${VERSION}.zip" Provisionsmanager95.exe LIESMICH.md ) echo "$VERSION" > dist/VERSION echo "== Setup (Inno Setup) ==" INNO_VERSION=6.7.3 INNO_SHA256=9c73c3bae7ed48d44112a0f48e66742c00090bdb5bef71d9d3c056c66e97b732 INNO_EXE=build/tmp/innosetup-$INNO_VERSION.exe mkdir -p build/tmp curl -fsSL -o "$INNO_EXE" "https://github.com/jrsoftware/issrc/releases/download/is-${INNO_VERSION//./_}/innosetup-$INNO_VERSION.exe" echo "$INNO_SHA256 $INNO_EXE" | sha256sum -c - timeout 300 wine "$INNO_EXE" /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- /CURRENTUSER '/DIR=C:\InnoSetup' rm -f dist/Provisionsmanager-Setup-*.exe timeout 300 wine 'C:\InnoSetup\ISCC.exe' /Q "/DAppVersion=$VERSION" 'build\installer.iss' SETUP="dist/Provisionsmanager-Setup-$VERSION.exe" test -f "$SETUP" echo "== Installer-Test (still installieren, Selbsttest, still deinstallieren) ==" winordner() { winepath -u "$(wine cmd /c echo "%$1%" | tr -d '\r')"; } # z. B. APPDATA -> /opt/wineprefix/... DATEN="$(winordner APPDATA)/Provisionsmanager95" ZIEL="$(winordner LOCALAPPDATA)/Programs/Provisionsmanager" mkdir -p "$DATEN" echo "Benutzerdaten" > "$DATEN/installer-test.txt" timeout 300 wine "$SETUP" /VERYSILENT /SUPPRESSMSGBOXES /CURRENTUSER /NORESTART test -f "$(winordner APPDATA)/Microsoft/Windows/Start Menu/Programs/Provisions-Manager.lnk" selbsttest "$ZIEL/Provisionsmanager.exe" timeout 300 wine "$ZIEL/unins000.exe" /VERYSILENT /SUPPRESSMSGBOXES /NORESTART # Der Deinstaller arbeitet als Kopie im Temp-Ordner weiter – auf das Ende warten for _ in $(seq 60); do [ -e "$ZIEL" ] || break; sleep 1; done if [ -e "$ZIEL" ]; then echo "Deinstallation FEHLGESCHLAGEN – Programmordner noch da:"; ls -la "$ZIEL"; exit 1; fi if [ ! -f "$DATEN/installer-test.txt" ]; then echo "Deinstallation hat Benutzerdaten gelöscht!"; exit 1; fi rm "$DATEN/installer-test.txt" echo "Installer-Test bestanden" ls -la dist