Selbst-Update im Docker-Betrieb direkt aus der Weboberfläche anstoßen (Host-Watcher wie in FilaDex) #16

Closed
opened 2026-09-26 04:58:13 +00:00 by AxonByteDev · 0 comments
Owner

Problem

Unter Einstellungen → Updates kann man bei einer Docker-Installation zwar sehen, dass es eine neue PatchPilot-Version gibt. „Update anwenden“ zeigt aber nur einen Befehl zum Kopieren an (manual_commands für Debian/Ubuntu), den man dann selbst per SSH auf dem Server ausführen muss. Das ist umständlich, und genau dafür ist PatchPilot eigentlich da.

Ziel: Das Update lässt sich direkt über die Weboberfläche anstoßen, ohne SSH, auf Debian und Ubuntu. Das Verfahren soll genau so funktionieren wie in FilaDex, wo das schon umgesetzt ist.

Stand in PatchPilot

  • backend/self_update.py:
    • Die Update-Prüfung gegen die Forgejo-Releases, die Kanäle beta/main, der Cache und list_releases() für einen gezielten Tag bzw. ein Downgrade gibt es schon.
    • apply_update() funktioniert nur bei Bare-Metal-Installationen (git checkout + pip + npm + os._exit(0) → systemd startet neu).
    • deployment_mode() erkennt Docker über /.dockerenv.
  • backend/routers/system_update.py → POST /api/system-update/apply: Bei Docker wird nichts ausgeführt, nur manual_command(s) zurückgegeben. Das ist eine bewusste Entscheidung: kein Zugriff auf den Docker-Socket, weil das faktisch root auf dem Host wäre.
  • frontend/src/pages/Settings.tsx (Tab Updates) zeigt bei Docker die Befehle zum Kopieren an (applyResult.manual_commands).
  • Installation laut Wiki (Debian/Ubuntu): /opt/patchpilot, Systembenutzer patchpilot (in der Gruppe docker), docker compose up -d --build.
    • Der Container läuft fest mit UID/GID 1000 (Dockerfile), und data/ gehört per chown -R 1000:1000 dieser UID.
    • Der Host-Benutzer patchpilot ist dagegen ein Systembenutzer mit einer anderen UID (useradd --system vergibt z. B. 999). ⚠️ Das ist wichtig für die Umsetzung, siehe unten.

So löst FilaDex das

Der Container bekommt weiterhin keinen Docker-Socket. Stattdessen verständigen sich Container und Host über eine Datei im gemeinsamen data/-Ordner:

  1. Anfordern: Klickt man auf „Update“, prüft das Backend den Ziel-Tag gegen die Forgejo-Release-Liste. Dann schreibt es data/update.request (JSON: tag, channel, requested_at), atomar über .tmp + rename, damit der Host keine halbe Datei liest. update.result wird gelöscht und update.log geleert.
  2. Auf dem Host reagieren: deploy/filadex-updater.path (systemd, PathExists=/opt/filadex/data/update.request) startet deploy/filadex-updater.service. Das ist Type=oneshot, läuft als Dienstbenutzer, nicht als root, mit TimeoutStartSec=3600.
  3. scripts/apply-update.sh ist die Sicherheitsgrenze. Das Script:
    • löscht die Anforderung beim Beenden immer per trap … EXIT, sonst würde die Path-Unit endlos neu auslösen,
    • prüft früh, ob es in data/ schreiben darf, und bricht sonst mit einer klaren Meldung ab (UID-Problem),
    • akzeptiert nur Tags aus der Forgejo-Release-Liste (ohne Drafts), damit selbst eine übernommene Weboberfläche keinen beliebigen Code auf den Host bringen kann,
    • merkt sich den aktuellen Stand (git describe --tags --exact-match bzw. rev-parse HEAD),
    • sichert die Datenbank und behält die letzten 5 Sicherungen,
    • führt git fetch --tags --prune → git checkout <tag> → APP_VERSION=<tag> docker compose up -d --build aus,
    • kehrt bei einem Fehler automatisch auf den vorherigen Stand zurück und baut ihn neu,
    • schreibt alle Ausgaben nach data/update.log und am Ende data/update.result (status ok/fehler, meldung, version).
  4. Rückmeldung in der Oberfläche:
    • GET /api/system/log ist ein SSE-Stream, der update.log Zeile für Zeile streamt und mit dem Ereignis fertig endet, sobald update.result da ist und update.request weg ist.
    • Bricht der Stream ab, weil der Container neu startet, fragt die Oberfläche den Status ab, bis PatchPilot wieder antwortet.
    • get_status() liefert zusätzlich laeuft (Anforderung liegt noch) und letztes_ergebnis.
  5. Hängende Anforderung: Hat sich an update.request/update.log länger als STILLSTAND_MINUTEN = 10 nichts geändert, wird die Anforderung beim nächsten Klick verworfen, mit dem Hinweis „Läuft der Watcher? systemctl status …-updater.path“. Sonst würde eine einzige liegengebliebene Datei alle weiteren Updates dauerhaft sperren.
  6. Gleiche UID auf beiden Seiten: In docker-compose.yml steht user: "${FILADEX_UID:-1000}:${FILADEX_GID:-1000}". Die echten Werte des Host-Benutzers stehen in der .env, und data/ gehört diesem Benutzer. Ohne das legt der Container Dateien an, die der Host-Dienst weder schreiben noch löschen kann, und das Update bleibt kommentarlos bei „Warte auf den Host-Dienst“ stehen.

Plan für PatchPilot

Backend

  • backend/self_update.py:
    • Konstanten DATA_DIR = REPO_ROOT / "data", REQUEST_FILE, RESULT_FILE, LOG_FILE, STALE_MINUTES = 10.
    • apply_update() aufteilen: den Tag bestimmen und gegen die Release-Liste prüfen (gibt es schon), dann _docker_request(tag) bzw. _baremetal_apply(tag) aufrufen. Die Bare-Metal-Variante bleibt inhaltlich gleich, schreibt aber zusätzlich nach LOG_FILE, damit beide Varianten dieselbe Log-Anzeige nutzen.
    • _docker_request(tag): Anforderung atomar schreiben, hängende Anforderungen erkennen und verwerfen, „läuft bereits“ melden, update.result löschen, update.log leeren.
    • get_status() um running (liegt REQUEST_FILE?) und last_result (Inhalt von RESULT_FILE) erweitern.
    • manual_docker_command(s) bleibt nur noch als Fallback im Status bzw. in der Fehlermeldung, für den Fall, dass der Watcher nicht eingerichtet ist.
  • backend/routers/system_update.py:
    • POST /apply legt bei Docker die Anforderung ab, statt nur den Befehl zurückzugeben.
    • Neuer Endpunkt GET /log als SSE-Stream auf data/update.log mit dem Ereignis fertig. Die Auth muss dabei wie beim bestehenden SSE-Log der Update-Läufe funktionieren, weil EventSource keine Header senden kann.
  • scheduled_check_and_maybe_apply(): Auto-Apply funktioniert damit auch bei Docker. Der Sonderfall „bei Docker nur benachrichtigen“ und der Hinweistext „Manueller Befehl nötig“ werden angepasst.

Host-Seite (neu)

  • deploy/patchpilot-updater.path: PathExists=/opt/patchpilot/data/update.request.
  • deploy/patchpilot-updater.service: Type=oneshot, User=patchpilot, Group=patchpilot, WorkingDirectory=/opt/patchpilot, After=/Requires=docker.service, TimeoutStartSec=3600.
  • scripts/apply-update.sh, übernommen aus FilaDex und angepasst:
    • REPO="AxonByteDev/PatchPilot", INSTALL_DIR="${PATCHPILOT_DIR:-/opt/patchpilot}".
    • Kanal-Logik: PatchPilot erkennt Beta über das prerelease-Flag, FilaDex über den Tag-Suffix. Für die Prüfung im Script spielt das keine Rolle, weil nur „Tag existiert als Release, kein Draft“ geprüft wird.
    • Datenbank-Sicherung: nur SQLite (data/orchestrator.db) über sqlite3.backup(), abgelegt als data/backups/patchpilot-<zeitstempel>.db. Die Postgres-Variante aus FilaDex entfällt.
    • APP_VERSION beim Build: docker-compose.yml erwartet laut Kommentar den Tag mit v (git describe). Das muss einheitlich sein, entweder APP_VERSION="${ZIEL_TAG}" oder überall ohne v, sonst zeigt die Oberfläche die Version danach anders an.
    • Rücksprung auf den vorherigen Stand wie in FilaDex.

UID-Problem (Voraussetzung, sonst funktioniert es nicht)

  • docker-compose.yml: user: "${PATCHPILOT_UID:-1000}:${PATCHPILOT_GID:-1000}" beim Dienst patchpilot ergänzen. Im Dockerfile bleibt der Benutzer 1000 als Default, nur /app/data muss für die tatsächliche UID beschreibbar sein. Das ist über den Bind-Mount gegeben, sobald data/ dem Host-Benutzer gehört.
  • data/ gehört danach dem Host-Benutzer patchpilot, nicht mehr UID 1000.

Einrichtung auf Debian und Ubuntu (einmalig, als root bzw. mit sudo)

Der einzige Unterschied ist su gegenüber sudo, die systemd-Units sind identisch. Anleitung im Wiki (Installation + Selbst-Update):

# Debian (als root)
cd /opt/patchpilot
printf 'PATCHPILOT_UID=%s\nPATCHPILOT_GID=%s\n' "$(id -u patchpilot)" "$(id -g patchpilot)" >> .env
chown -R patchpilot:patchpilot data
cp deploy/patchpilot-updater.path deploy/patchpilot-updater.service /etc/systemd/system/
systemctl daemon-reload && systemctl enable --now patchpilot-updater.path
su - patchpilot -s /bin/bash -c 'cd /opt/patchpilot && docker compose up -d'

# Ubuntu: dieselben Befehle mit sudo, der letzte als
sudo -u patchpilot -H bash -c 'cd /opt/patchpilot && docker compose up -d'

Wichtig: enable --now statt nur enable, sonst wartet bis zum nächsten Neustart des Servers niemand auf die Anforderung (in FilaDex genau so passiert).

Bestehende Installationen: Das allererste Update auf die Version mit Watcher muss noch von Hand laufen (bisheriger Befehl), danach einmal die Einrichtung oben ausführen. Das gehört in die Release-Notes. Optional ein kleines scripts/install-updater.sh, das die Schritte oben idempotent für Debian und Ubuntu erledigt.

Frontend (Settings.tsx, Tab Updates)

  • Bei Docker zeigt „Update anwenden“ / „Auf diese Version wechseln“ keine Befehlsbox mehr, sondern startet das Update:
    • Status „Warte auf den Host-Dienst …“ → Live-Log über EventSource (Log-Box, die in sich scrollt, nicht die ganze Seite; in FilaDex auch so behoben).
    • Bricht die Verbindung ab, weil der Container neu startet, fragt die Oberfläche den Status ab, bis PatchPilot wieder antwortet, und zeigt dann die neue Version bzw. das Ergebnis aus last_result.
    • Kommt nach einigen Minuten keine Antwort, erscheint der Hinweis journalctl -u patchpilot-updater.service.
  • Die Befehlsbox bleibt als Fallback sichtbar (z. B. aufklappbar „Manuell aktualisieren“), falls der Watcher nicht eingerichtet ist oder die Anforderung als hängend verworfen wurde.
  • last_result nach einem Update anzeigen (ok / fehlgeschlagen + ggf. „Rücksprung auf vX erfolgreich“).

Nicht Teil dieses Issues

Aus FilaDex bewusst nicht übernommen: PostgreSQL-Sicherung, der komplette install.sh/uninstall.sh-Installer und filadex.service (Start beim Booten; PatchPilot regelt das über restart: unless-stopped).

Akzeptanzkriterien

  • Bei einer Docker-Installation (Debian und Ubuntu) startet „Update anwenden“ das Update ohne SSH
  • Ein gezielter Wechsel auf einen Release-Tag (auch ein Downgrade) funktioniert genauso
  • Das Host-Script akzeptiert nur Tags aus der Forgejo-Release-Liste und lehnt alles andere mit einer Meldung ab
  • Vor dem Update wird die SQLite-Datenbank gesichert, die letzten 5 Sicherungen bleiben erhalten
  • Schlägt der Build oder Start fehl, springt das Script automatisch auf den vorherigen Stand zurück
  • Live-Log in der Oberfläche; nach dem Neustart des Containers meldet sich die Seite von selbst mit Ergebnis zurück
  • Hängende Anforderungen (> 10 min ohne Regung) sperren weitere Updates nicht dauerhaft
  • Container und Host-Dienst nutzen dieselbe UID (PATCHPILOT_UID/GID), und das Script erkennt fehlende Schreibrechte früh
  • Automatisches Update per Zeitplan (auto_apply) funktioniert auch bei Docker
  • Bare-Metal-Update funktioniert unverändert weiter
  • Wiki (Installation + Selbst-Update) für Debian und Ubuntu aktualisiert, dazu ein Hinweis für bestehende Installationen in den Release-Notes
  • Tests: Anforderung schreiben, hängende Anforderung erkennen, Status mit running/last_result, /apply bei Docker
## Problem Unter **Einstellungen → Updates** kann man bei einer Docker-Installation zwar sehen, dass es eine neue PatchPilot-Version gibt. „Update anwenden“ zeigt aber nur einen Befehl zum Kopieren an (`manual_commands` für Debian/Ubuntu), den man dann selbst per SSH auf dem Server ausführen muss. Das ist umständlich, und genau dafür ist PatchPilot eigentlich da. Ziel: **Das Update lässt sich direkt über die Weboberfläche anstoßen, ohne SSH**, auf Debian und Ubuntu. Das Verfahren soll genau so funktionieren wie in **[FilaDex](https://git.hippler.one/AxonByteDev/FilaDex)**, wo das schon umgesetzt ist. ## Stand in PatchPilot - `backend/self_update.py`: - Die Update-Prüfung gegen die Forgejo-Releases, die Kanäle `beta`/`main`, der Cache und `list_releases()` für einen gezielten Tag bzw. ein Downgrade gibt es schon. - `apply_update()` funktioniert **nur bei Bare-Metal-Installationen** (`git checkout` + pip + npm + `os._exit(0)` → systemd startet neu). - `deployment_mode()` erkennt Docker über `/.dockerenv`. - `backend/routers/system_update.py` → `POST /api/system-update/apply`: Bei Docker wird **nichts ausgeführt**, nur `manual_command(s)` zurückgegeben. Das ist eine bewusste Entscheidung: kein Zugriff auf den Docker-Socket, weil das faktisch root auf dem Host wäre. - `frontend/src/pages/Settings.tsx` (Tab Updates) zeigt bei Docker die Befehle zum Kopieren an (`applyResult.manual_commands`). - Installation laut Wiki (Debian/Ubuntu): `/opt/patchpilot`, Systembenutzer `patchpilot` (in der Gruppe `docker`), `docker compose up -d --build`. - Der Container läuft **fest mit UID/GID 1000** (`Dockerfile`), und `data/` gehört per `chown -R 1000:1000` dieser UID. - Der Host-Benutzer `patchpilot` ist dagegen ein Systembenutzer mit einer **anderen UID** (`useradd --system` vergibt z. B. 999). ⚠️ Das ist wichtig für die Umsetzung, siehe unten. ## So löst FilaDex das Der Container bekommt weiterhin **keinen** Docker-Socket. Stattdessen verständigen sich Container und Host über eine Datei im gemeinsamen `data/`-Ordner: 1. **Anfordern:** Klickt man auf „Update“, prüft das Backend den Ziel-Tag gegen die Forgejo-Release-Liste. Dann schreibt es `data/update.request` (JSON: `tag`, `channel`, `requested_at`), atomar über `.tmp` + `rename`, damit der Host keine halbe Datei liest. `update.result` wird gelöscht und `update.log` geleert. 2. **Auf dem Host reagieren:** `deploy/filadex-updater.path` (systemd, `PathExists=/opt/filadex/data/update.request`) startet `deploy/filadex-updater.service`. Das ist `Type=oneshot`, läuft als **Dienstbenutzer, nicht als root**, mit `TimeoutStartSec=3600`. 3. **`scripts/apply-update.sh` ist die Sicherheitsgrenze.** Das Script: - löscht die Anforderung beim Beenden immer per `trap … EXIT`, sonst würde die Path-Unit endlos neu auslösen, - prüft früh, ob es in `data/` schreiben darf, und bricht sonst mit einer klaren Meldung ab (UID-Problem), - akzeptiert **nur Tags aus der Forgejo-Release-Liste** (ohne Drafts), damit selbst eine übernommene Weboberfläche keinen beliebigen Code auf den Host bringen kann, - merkt sich den aktuellen Stand (`git describe --tags --exact-match` bzw. `rev-parse HEAD`), - sichert die Datenbank und behält die letzten 5 Sicherungen, - führt `git fetch --tags --prune` → `git checkout <tag>` → `APP_VERSION=<tag> docker compose up -d --build` aus, - kehrt bei einem Fehler **automatisch auf den vorherigen Stand zurück** und baut ihn neu, - schreibt alle Ausgaben nach `data/update.log` und am Ende `data/update.result` (`status` ok/fehler, `meldung`, `version`). 4. **Rückmeldung in der Oberfläche:** - `GET /api/system/log` ist ein SSE-Stream, der `update.log` Zeile für Zeile streamt und mit dem Ereignis `fertig` endet, sobald `update.result` da ist und `update.request` weg ist. - Bricht der Stream ab, weil der Container neu startet, fragt die Oberfläche den Status ab, bis PatchPilot wieder antwortet. - `get_status()` liefert zusätzlich `laeuft` (Anforderung liegt noch) und `letztes_ergebnis`. 5. **Hängende Anforderung:** Hat sich an `update.request`/`update.log` länger als `STILLSTAND_MINUTEN = 10` nichts geändert, wird die Anforderung beim nächsten Klick verworfen, mit dem Hinweis „Läuft der Watcher? `systemctl status …-updater.path`“. Sonst würde eine einzige liegengebliebene Datei alle weiteren Updates dauerhaft sperren. 6. **Gleiche UID auf beiden Seiten:** In `docker-compose.yml` steht `user: "${FILADEX_UID:-1000}:${FILADEX_GID:-1000}"`. Die echten Werte des Host-Benutzers stehen in der `.env`, und `data/` gehört diesem Benutzer. Ohne das legt der Container Dateien an, die der Host-Dienst weder schreiben noch löschen kann, und das Update bleibt kommentarlos bei „Warte auf den Host-Dienst“ stehen. ## Plan für PatchPilot ### Backend - `backend/self_update.py`: - Konstanten `DATA_DIR = REPO_ROOT / "data"`, `REQUEST_FILE`, `RESULT_FILE`, `LOG_FILE`, `STALE_MINUTES = 10`. - `apply_update()` aufteilen: den Tag bestimmen und gegen die Release-Liste prüfen (gibt es schon), dann `_docker_request(tag)` bzw. `_baremetal_apply(tag)` aufrufen. Die Bare-Metal-Variante bleibt inhaltlich gleich, schreibt aber zusätzlich nach `LOG_FILE`, damit beide Varianten dieselbe Log-Anzeige nutzen. - `_docker_request(tag)`: Anforderung atomar schreiben, hängende Anforderungen erkennen und verwerfen, „läuft bereits“ melden, `update.result` löschen, `update.log` leeren. - `get_status()` um `running` (liegt `REQUEST_FILE`?) und `last_result` (Inhalt von `RESULT_FILE`) erweitern. - `manual_docker_command(s)` bleibt nur noch als **Fallback** im Status bzw. in der Fehlermeldung, für den Fall, dass der Watcher nicht eingerichtet ist. - `backend/routers/system_update.py`: - `POST /apply` legt bei Docker die Anforderung ab, statt nur den Befehl zurückzugeben. - Neuer Endpunkt `GET /log` als SSE-Stream auf `data/update.log` mit dem Ereignis `fertig`. Die Auth muss dabei wie beim bestehenden SSE-Log der Update-Läufe funktionieren, weil `EventSource` keine Header senden kann. - `scheduled_check_and_maybe_apply()`: Auto-Apply funktioniert damit auch bei Docker. Der Sonderfall „bei Docker nur benachrichtigen“ und der Hinweistext „Manueller Befehl nötig“ werden angepasst. ### Host-Seite (neu) - `deploy/patchpilot-updater.path`: `PathExists=/opt/patchpilot/data/update.request`. - `deploy/patchpilot-updater.service`: `Type=oneshot`, `User=patchpilot`, `Group=patchpilot`, `WorkingDirectory=/opt/patchpilot`, `After=`/`Requires=docker.service`, `TimeoutStartSec=3600`. - `scripts/apply-update.sh`, übernommen aus FilaDex und angepasst: - `REPO="AxonByteDev/PatchPilot"`, `INSTALL_DIR="${PATCHPILOT_DIR:-/opt/patchpilot}"`. - **Kanal-Logik:** PatchPilot erkennt Beta über das `prerelease`-Flag, FilaDex über den Tag-Suffix. Für die Prüfung im Script spielt das keine Rolle, weil nur „Tag existiert als Release, kein Draft“ geprüft wird. - **Datenbank-Sicherung:** nur SQLite (`data/orchestrator.db`) über `sqlite3.backup()`, abgelegt als `data/backups/patchpilot-<zeitstempel>.db`. Die Postgres-Variante aus FilaDex entfällt. - `APP_VERSION` beim Build: `docker-compose.yml` erwartet laut Kommentar den Tag **mit** `v` (`git describe`). Das muss einheitlich sein, entweder `APP_VERSION="${ZIEL_TAG}"` oder überall ohne `v`, sonst zeigt die Oberfläche die Version danach anders an. - Rücksprung auf den vorherigen Stand wie in FilaDex. ### UID-Problem (Voraussetzung, sonst funktioniert es nicht) - `docker-compose.yml`: `user: "${PATCHPILOT_UID:-1000}:${PATCHPILOT_GID:-1000}"` beim Dienst `patchpilot` ergänzen. Im `Dockerfile` bleibt der Benutzer 1000 als Default, nur `/app/data` muss für die tatsächliche UID beschreibbar sein. Das ist über den Bind-Mount gegeben, sobald `data/` dem Host-Benutzer gehört. - `data/` gehört danach dem Host-Benutzer `patchpilot`, nicht mehr UID 1000. ### Einrichtung auf Debian und Ubuntu (einmalig, als root bzw. mit sudo) Der einzige Unterschied ist `su` gegenüber `sudo`, die systemd-Units sind identisch. Anleitung im Wiki (Installation + Selbst-Update): ```bash # Debian (als root) cd /opt/patchpilot printf 'PATCHPILOT_UID=%s\nPATCHPILOT_GID=%s\n' "$(id -u patchpilot)" "$(id -g patchpilot)" >> .env chown -R patchpilot:patchpilot data cp deploy/patchpilot-updater.path deploy/patchpilot-updater.service /etc/systemd/system/ systemctl daemon-reload && systemctl enable --now patchpilot-updater.path su - patchpilot -s /bin/bash -c 'cd /opt/patchpilot && docker compose up -d' # Ubuntu: dieselben Befehle mit sudo, der letzte als sudo -u patchpilot -H bash -c 'cd /opt/patchpilot && docker compose up -d' ``` Wichtig: `enable --now` statt nur `enable`, sonst wartet bis zum nächsten Neustart des Servers niemand auf die Anforderung (in FilaDex genau so passiert). **Bestehende Installationen:** Das allererste Update auf die Version mit Watcher muss noch von Hand laufen (bisheriger Befehl), danach einmal die Einrichtung oben ausführen. Das gehört in die Release-Notes. Optional ein kleines `scripts/install-updater.sh`, das die Schritte oben idempotent für Debian und Ubuntu erledigt. ### Frontend (`Settings.tsx`, Tab Updates) - Bei Docker zeigt „Update anwenden“ / „Auf diese Version wechseln“ keine Befehlsbox mehr, sondern startet das Update: - Status „Warte auf den Host-Dienst …“ → Live-Log über `EventSource` (Log-Box, die in sich scrollt, nicht die ganze Seite; in FilaDex auch so behoben). - Bricht die Verbindung ab, weil der Container neu startet, fragt die Oberfläche den Status ab, bis PatchPilot wieder antwortet, und zeigt dann die neue Version bzw. das Ergebnis aus `last_result`. - Kommt nach einigen Minuten keine Antwort, erscheint der Hinweis `journalctl -u patchpilot-updater.service`. - Die Befehlsbox bleibt als **Fallback** sichtbar (z. B. aufklappbar „Manuell aktualisieren“), falls der Watcher nicht eingerichtet ist oder die Anforderung als hängend verworfen wurde. - `last_result` nach einem Update anzeigen (ok / fehlgeschlagen + ggf. „Rücksprung auf vX erfolgreich“). ### Nicht Teil dieses Issues Aus FilaDex bewusst **nicht** übernommen: PostgreSQL-Sicherung, der komplette `install.sh`/`uninstall.sh`-Installer und `filadex.service` (Start beim Booten; PatchPilot regelt das über `restart: unless-stopped`). ## Akzeptanzkriterien - [x] Bei einer Docker-Installation (Debian und Ubuntu) startet „Update anwenden“ das Update ohne SSH - [x] Ein gezielter Wechsel auf einen Release-Tag (auch ein Downgrade) funktioniert genauso - [x] Das Host-Script akzeptiert nur Tags aus der Forgejo-Release-Liste und lehnt alles andere mit einer Meldung ab - [x] Vor dem Update wird die SQLite-Datenbank gesichert, die letzten 5 Sicherungen bleiben erhalten - [x] Schlägt der Build oder Start fehl, springt das Script automatisch auf den vorherigen Stand zurück - [x] Live-Log in der Oberfläche; nach dem Neustart des Containers meldet sich die Seite von selbst mit Ergebnis zurück - [x] Hängende Anforderungen (> 10 min ohne Regung) sperren weitere Updates nicht dauerhaft - [x] Container und Host-Dienst nutzen dieselbe UID (`PATCHPILOT_UID/GID`), und das Script erkennt fehlende Schreibrechte früh - [x] Automatisches Update per Zeitplan (`auto_apply`) funktioniert auch bei Docker - [x] Bare-Metal-Update funktioniert unverändert weiter - [x] Wiki (Installation + Selbst-Update) für Debian und Ubuntu aktualisiert, dazu ein Hinweis für bestehende Installationen in den Release-Notes - [x] Tests: Anforderung schreiben, hängende Anforderung erkennen, Status mit `running`/`last_result`, `/apply` bei Docker
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
AxonByteDev/PatchPilot#16
No description provided.