# Release-Pakete bauen ## Überblick Der Updater rollt ein ZIP über den Anwendungsstamm aus: Jede Datei im Paket wird an dieselbe relative Position im Projekt kopiert. Damit das funktioniert, muss das Paket richtig geschnitten sein. Relevante Dateien: - `manage-client/lib/updater.php` – Prüfung, Entpacken, Ausrollen - in diesem Paket: `scripts/create-release-zip.sh` – fertiges Build-Skript ## Aufbau des Pakets Die Wurzel des ZIP **ist** der Anwendungsstamm. Kein zusätzliches Oberverzeichnis: ```text richtig falsch ------ ------ index.php meinprojekt-v1.3.0/index.php admin/orders.php meinprojekt-v1.3.0/admin/orders.php includes/version.php meinprojekt-v1.3.0/includes/version.php manage-client/lib/client.php migrations/2026-08-20-01-x.php ``` Ein Paket mit Oberverzeichnis würde das Projekt nicht aktualisieren, sondern einen neuen Unterordner anlegen. ## Was hineingehört - alle Anwendungsdateien - `includes/version.php` (oder die konfigurierte Versionsdatei) mit der **neuen** Version - `manage-client/` **ohne** `config.php` – so wird der Client mit aktualisiert - `migrations/`, sofern das Release Migrationen mitbringt ## Was draußen bleiben muss | Ausschluss | Grund | |---|---| | `config.php` | enthält Zugangsdaten der Zielinstallation | | `manage-client/config.php` | enthält Instanz-Token der Zielinstallation | | `data/` | Betriebsdaten der Zielinstallation | | `.git/` | gehört nicht auf einen Produktivserver | | `build/`, `storage/` | Artefakte | `config.php`, `data/` und `.git/` sind zusätzlich über `MANAGE_UPDATE_PROTECTED_PATHS` geschützt: Selbst wenn sie versehentlich im Paket landen, werden sie beim Ausrollen übersprungen. Der Ausschluss beim Bauen ist trotzdem nötig, weil das Paket sonst fremde Zugangsdaten enthält und auf dem Manage-Server heruntergeladen werden kann. ## Versionsnummer Das Format ist `vX.Y.Z` – ohne Suffix, ohne Präfix. Sowohl der Client als auch der Server lehnen alles andere ab. Die Version steht an genau einer Stelle: in der Versionsdatei innerhalb des Pakets. Der Client schreibt sie nie selbst; sie ändert sich als Nebeneffekt des Dateikopierens. Wird sie beim Bauen vergessen, meldet die Instanz nach dem Update weiterhin die alte Version und bietet dasselbe Update erneut an. ## Build mit dem mitgelieferten Skript Dieses Paket enthält `scripts/create-release-zip.sh`. Das Skript wird nach `scripts/` des Projekts kopiert, einmal pro Projekt am Kopf angepasst (Produktname, Versionsdatei, Ausschlüsse) und dann im Projektverzeichnis aufgerufen: ```bash ./scripts/create-release-zip.sh v1.3.0 ``` Das Skript 1. schreibt die Version in die Versionsdatei, 2. packt alle von Git verfolgten Dateien abzüglich der Ausschlussliste, 3. gibt SHA-256 und Größe aus. Es verwendet `git ls-files`, damit nur eingecheckte Dateien im Paket landen – lokale Experimente und ignorierte Dateien bleiben automatisch draußen. ## Build von Hand ```bash cd /pfad/zum/projekt zip -r ../meinprojekt-v1.3.0.zip . \ -x 'config.php' \ 'manage-client/config.php' \ 'data/*' \ '.git/*' \ 'build/*' ``` Prüfen, was tatsächlich drin ist – dieser Schritt lohnt sich immer: ```bash unzip -l ../meinprojekt-v1.3.0.zip | head -30 ``` ## Veröffentlichen Im Manage-Server unter **Releases**: Version eintragen, ZIP hochladen. Prüfsumme und Größe berechnet der Server selbst; sie werden nie vom Hochladenden übernommen. Ein Upload setzt das Release automatisch als aktuell. ## Was der Client beim Ausrollen prüft 1. Größe und SHA-256 müssen dem Manifest entsprechen, sonst wird die Datei gelöscht. 2. Jeder Eintrag im ZIP wird gegen Pfad-Ausbruch geprüft (`..`, absolute Pfade, Laufwerksbuchstaben, Nullbytes). 3. Das Paket muss mindestens einen der Pfade aus `MANAGE_UPDATE_SANITY_PATHS` enthalten. 4. Beim Kopieren wird jede vorhandene Zieldatei zuerst nach `MANAGE_UPDATE_BACKUP_DIR` gesichert. ## Grenzen des Verfahrens - **Gelöschte Dateien werden nicht entfernt.** Das Ausrollen ist ein Überlagern. Eine Datei, die es im neuen Release nicht mehr gibt, bleibt in der Installation liegen. Soll sie wirklich verschwinden, gehört das in eine Migration. - **Kein Wartungsmodus.** Die Anwendung bleibt während des Kopierens erreichbar. Bei größeren Umbauten sollte in einer Randzeit aktualisiert werden. - **Keine Rücknahme.** Die Sicherungskopien in `MANAGE_UPDATE_BACKUP_DIR` sind für die manuelle Wiederherstellung gedacht; es gibt keinen Befehl dafür. Aufbewahrt wird nur der letzte Lauf. ## Weiter - [07_POST_UPDATE_HOOKS](07_POST_UPDATE_HOOKS.md) – Migrationen im Paket - [04_FUNCTION_API](04_FUNCTION_API.md) – `manageUpdateApply()`