Release v1.0.1 #2
Loading…
Reference in a new issue
No description provided.
Delete branch "beta"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Das Selbst-Update konnte auf einem frisch installierten Server nie funktionieren. Im Journal: apply-update.sh: /opt/filadex/data/update.log: Permission denied rm: cannot remove '/opt/filadex/data/update.request': Permission denied Der Prozess im Container lief fest auf UID 1000, der Dienstbenutzer auf dem Host dagegen auf dem, was `useradd --system` gerade frei fand — also unter 1000. Beide greifen über den Bind-Mount auf denselben Ordner zu. Der Container legte dort Dateien an, die der Update-Dienst weder beschreiben noch löschen konnte. Der Kommentar im Dockerfile beschrieb die Annahme sogar ("muss mit den Rechten des host-seitigen Bind-Mounts übereinstimmen") — der Installer hat sie nur nie erfüllt: Er setzte data/ auf 1000:1000, also auf die Kennung des Containers statt auf die des Benutzers, der damit arbeiten muss. Maßgeblich ist jetzt der Host: Seine UID lässt sich nicht frei wählen, die des Containers schon. Der Installer ermittelt sie, trägt sie als FILADEX_UID und FILADEX_GID in die .env ein, und docker-compose.yml startet den Container damit. data/ wird auf dieselbe Kennung gezogen — auch nachträglich, sodass eine bestehende Installation sich mit einem erneuten Aufruf des Installers einrenkt. Die Folgen waren schwerer zu deuten als die Ursache: Weil die Anforderung liegen blieb, löste die Path-Unit sofort wieder aus, und systemd sperrte den Dienst schließlich wegen zu häufiger Startversuche. In der Oberfläche sah das aus wie ein Watcher, der gar nicht läuft — dieselbe Anzeige wie beim vorigen Fehler, aber eine völlig andere Ursache. Deshalb prüft apply-update.sh die Schreibrechte jetzt einmal am Anfang und scheitert mit einer Meldung, die beide UIDs nennt und den Befehl zum Beheben, statt sich mit "Permission denied" durch jeden Schritt zu kämpfen. Bleibt die Anforderung trotzdem liegen, sagt das Skript ausdrücklich, dass es deshalb gleich wieder gestartet wird. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>Im Container läuft FilaDex jetzt gegen PostgreSQL 17 in einem eigenen Dienst. Welche Datenbank es ist, entscheidet allein DATABASE_URL — lokal und in der Testsuite bleibt SQLite der Standard, weil dort weder Server noch Container nötig sind. Zwei Datenbanken zu unterstützen ist kein Selbstzweck: Ohne SQLite bräuchte jeder Testlauf und jeder Start von dev.sh einen laufenden Docker-Daemon, und genau der ist auf einem Entwicklungsrechner das Unzuverlässigste am Aufbau. Mit SQLite allein wäre die Testsuite dagegen kein Beweis mehr für den Betrieb. Deshalb läuft dieselbe Suite auf Wunsch gegen einen echten Server: ./scripts/check.sh --postgres Das hat sich sofort ausgezahlt. PostgreSQL verwirft nach einer fehlgeschlagenen Anweisung die gesamte Transaktion — die bisherige Migrationslogik führte ALTER TABLE blind aus und verschluckte den Fehler "Spalte existiert schon". Unter SQLite ging das gut; unter PostgreSQL hätte die erste vorhandene Spalte alle folgenden Migrationen blockiert, mit "current transaction is aborted". Jetzt wird vorher nachgesehen, statt hinterher gedeutet — auch ohne den Unterschied zwischen den Datenbanken die ehrlichere Variante. Die Sicherung kann beide Formen: pg_dump für PostgreSQL, die Backup-Funktion für SQLite. Beide Endungen werden gemeinsam rotiert, sonst bliebe nach einem Wechsel die alte Sorte für immer liegen. pg_dump läuft im Datenbankcontainer selbst, damit Client und Server zusammenpassen, ohne dass jemand daran denken muss. postgresql-client-17 im Dockerfile und postgres:17-alpine in docker-compose.yml gehören zusammen und sind beide ausdrücklich festgenagelt, das Basisimage gleich mit. Ein neuerer Client schreibt Anweisungen, die ein älterer Server nicht kennt; beim Zurückspielen sieht das nach einer kaputten Sicherung aus. Einer Sicherung, der man nicht traut, nützt niemandem. Der Installer erzeugt das Datenbankpasswort einmalig und fasst es danach nie wieder an — ein neues Passwort würde den bestehenden Datenbestand unzugänglich machen, weil der Benutzer nur beim allerersten Start angelegt wird. Ohne Passwort startet docker compose bewusst gar nicht erst, statt mit einem Standardwert zu laufen. dev.sh legt für den Container-Betrieb eine .env an, und --reset wirft jetzt auch das Docker-Volume weg, sonst überlebte der Bestand einen "Reset". Geprüft: 360 Tests gegen SQLite und dieselben 360 gegen PostgreSQL 17. Dazu der komplette Stack im Container — Seed-Daten, Beispielbestand über die API, Vollsicherung aus der Oberfläche, Schema komplett gelöscht und aus dem Dump zurückgespielt: 12 Rollen und 90 Buchungen wieder da, null Fehlerzeilen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>Zwei Fehler, die zusammen dafür sorgten, dass Versionsnummern verloren gingen. In der Release-Liste fehlten dadurch v1.0.1-beta.5 und -beta.7, obwohl beide Tags existierten — Installationen im Kanal "beta" haben diese Versionen nie zu sehen bekommen. **Der Wettlauf.** Beim Push eines Tags legt Forgejo im Hintergrund selbst einen Eintrag dafür an. Kommt unser API-Aufruf dazwischen, scheitert er an der Eindeutigkeit: unique constraint violation: duplicate key value violates "UQE_release_n" Der Eintrag ist dabei weder unter /releases noch unter /releases/tags/<tag> zu sehen, es gibt also nichts zu reparieren — man muss schlicht einen Moment warten. Gegen das echte Forgejo nachgestellt: derselbe Aufruf, der eben noch mit HTTP 500 scheiterte, liefert beim zweiten Mal 201. Das Skript versucht es jetzt bis zu fünfmal mit wachsendem Abstand. **Die übersprungene Nummer.** Bricht ein Lauf nach dem Tag-Push ab, ist der Tag oben und der Eintrag fehlt. Der nächste Aufruf zählte einfach weiter — die angefangene Version blieb als Lücke zurück. Jetzt sieht das Skript nach, ob zum höchsten vorhandenen Tag ein Eintrag fehlt, und bietet an, diesen Stand nachzutragen statt einen neuen anzufangen. Gefragt wird nur bei einem eindeutigen 404. Ein nicht erreichbarer Server oder ein abgelehnter Token heißt "weiß nicht", nicht "fehlt" — sonst wollte das Skript einen längst fertigen Release nachtragen. Gegen das echte Forgejo lesend geprüft: 200 bei vorhandenen Einträgen, 404 bei einem erfundenen Tag, 000 bei totem Server. Beim Nachtragen zählt der Changelog bis zum Tag statt bis HEAD. Sonst stünden im Eintrag Änderungen, die in dieser Version gar nicht drin sind. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>