docs(quick-260914-ku1): Betriebshandbuch — Zwei Kanäle Live und Beta, Freigabe, Hotfix ohne Datenbankänderung, neuer Live-Server; ci-cd-setup auf gemessenen Stand
- anleitung-betrieb.md: neues Kapitel 9 (Kanal, IMAGE_TAG je Server, Freigabe, Hotfix-Ablauf mit Regel "Keine Datenbankaenderung als Hotfix", drei Kontrollwege, Einrichtung des Live-Servers, Erstfreigabe v1.0.0); Inhaltsverzeichnis, Tabelle in Kapitel 1, IMAGE_TAG in Kapitel 3, Etiketten in Kapitel 4, Startzeile in Kapitel 7 - ci-cd-setup.md: REGISTRY_TOKEN und Push ueber localhost:3002, Trigger main/live/v*, Jobs quality -> test -> publish, Etiketten- und Build-Arg-Tabellen, D-13 ueberholt, Tag-/Branch-Schutz-Empfehlung (T-KU1-04), Fehlerbehebung fuer den Stempel Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
This commit is contained in:
+184
-9
@@ -19,6 +19,7 @@ Betrieb der bereits laufenden Installation, nicht deren automatisierten Build.
|
||||
6. [Sicherung und Wiederherstellung](#6-sicherung-und-wiederherstellung)
|
||||
7. [Protokolle und Fehlersuche](#7-protokolle-und-fehlersuche)
|
||||
8. [Abgrenzung zur CI/CD-Pipeline](#8-abgrenzung-zur-cicd-pipeline)
|
||||
9. [Zwei Kanäle: Live und Beta](#9-zwei-kanäle-live-und-beta)
|
||||
|
||||
---
|
||||
|
||||
@@ -29,8 +30,8 @@ Tessera besteht aus drei Containern, definiert in `docker-compose.yml` (Basis) u
|
||||
|
||||
| Dienst | Image / Build | Host-Port | Zweck |
|
||||
|--------|---------------|-----------|-------|
|
||||
| `web` | `apps/web/Dockerfile` (Basis) bzw. `git.vicolab.de/schalli/tessera-ctl/web:latest` (Prod) | 3000 | Next.js-Frontend (Portal, Dashboard) |
|
||||
| `api` | `apps/api/Dockerfile` (Basis) bzw. `git.vicolab.de/schalli/tessera-ctl/api:latest` (Prod) | 3001 | NestJS-Backend (REST-API, Prisma/PostgreSQL-Zugriff) |
|
||||
| `web` | `apps/web/Dockerfile` (Basis) bzw. `git.vicolab.de/schalli/tessera-ctl/web:${IMAGE_TAG}` (Prod; `beta` oder `live`, siehe Kapitel 9) | 3000 | Next.js-Frontend (Portal, Dashboard) |
|
||||
| `api` | `apps/api/Dockerfile` (Basis) bzw. `git.vicolab.de/schalli/tessera-ctl/api:${IMAGE_TAG}` (Prod; `beta` oder `live`, siehe Kapitel 9) | 3001 | NestJS-Backend (REST-API, Prisma/PostgreSQL-Zugriff) |
|
||||
| `db` | `postgres:16-alpine` | kein Host-Port | PostgreSQL-Datenbank |
|
||||
|
||||
Zusätzlich existiert `docker-compose.dev.yml` (Bind-Mounts für Live-Reload,
|
||||
@@ -159,6 +160,7 @@ Zugangsdaten.
|
||||
| `TESSERA_SMTP_HOST` / `_PORT` / `_SECURE` / `_USER` / `_PASSWORD` / `_FROM` | nein (aber ohne Host kein Mailversand) | Host leer, Port `587`, `_SECURE=false` | SMTP-Relay für ausgehende Mails (Passwort-Reset, Benachrichtigungen). |
|
||||
| `APP_URL` | empfohlen | `http://localhost:3001` (für `NEXT_PUBLIC_API_URL`) / `http://localhost:3000` (für `TESSERA_APP_URL`) | Öffentliche Basis-URL der Web-Oberfläche. Wird serverseitig u. a. für in E-Mails generierte Links verwendet (`TESSERA_APP_URL`). |
|
||||
| `API_INTERNAL_URL` | fest verdrahtet | `http://api:3001` | Adresse, unter der `web` die API **innerhalb** des Docker-Netzes erreicht; dorthin schreibt Next.js die `/api-proxy/*`-Rewrites um. In der Regel nicht ändern. |
|
||||
| `IMAGE_TAG` | empfohlen | `beta` | Welcher Kanal auf diesem Server läuft: `beta` (alle Neuerungen, alpha) oder `live` (nur freigegebene Versionen, tessera.ctl.de). Siehe Kapitel 9. |
|
||||
|
||||
Hinweis zu `NEXT_PUBLIC_API_URL`: Diese Variable wird beim Image-Build bereits fest
|
||||
auf `/api-proxy` gesetzt (`ENV NEXT_PUBLIC_API_URL=/api-proxy` in
|
||||
@@ -191,7 +193,7 @@ docker compose -f docker-compose.prod.yml up -d --force-recreate api web
|
||||
**Verifizierte Falle:** `docker compose up -d` **ohne** `--force-recreate` ersetzt
|
||||
einen bereits laufenden Container **nicht**, wenn Compose der Meinung ist, an der
|
||||
Service-Definition habe sich nichts geändert – auch wenn `pull` gerade ein neues
|
||||
Image unter demselben Tag (`:latest`) heruntergeladen hat. Der alte Container läuft
|
||||
Image unter demselben Etikett (`beta` bzw. `live`) heruntergeladen hat. Der alte Container läuft
|
||||
dann unverändert mit dem alten Code weiter, ohne Fehlermeldung. Das Deployment
|
||||
wirkt erfolgreich, ist es aber nicht. Dieser Fehler ist dem Team schon mehrfach
|
||||
passiert. Deshalb: nach jedem `pull` **immer** `--force-recreate` verwenden (nur
|
||||
@@ -204,12 +206,15 @@ Erstellungszeitpunkt des zugehörigen Images vergleichen. Der Container muss
|
||||
|
||||
```bash
|
||||
docker inspect -f '{{.State.StartedAt}}' tessera-api-1
|
||||
docker image inspect -f '{{.Created}}' git.vicolab.de/schalli/tessera-ctl/api:latest
|
||||
docker image inspect -f '{{.Created}}' git.vicolab.de/schalli/tessera-ctl/api:beta
|
||||
|
||||
docker inspect -f '{{.State.StartedAt}}' tessera-web-1
|
||||
docker image inspect -f '{{.Created}}' git.vicolab.de/schalli/tessera-ctl/web:latest
|
||||
docker image inspect -f '{{.Created}}' git.vicolab.de/schalli/tessera-ctl/web:beta
|
||||
```
|
||||
|
||||
(Auf dem Live-Server statt `:beta` jeweils `:live` einsetzen – das Etikett, das in
|
||||
der `.env` als `IMAGE_TAG` steht, siehe Kapitel 9.)
|
||||
|
||||
(Container-Namen mit `docker compose -f docker-compose.prod.yml ps` prüfen, falls
|
||||
sie auf dem Server abweichen.) Liegt `StartedAt` **vor** `Created` des Images, läuft
|
||||
noch die alte Version – dann `--force-recreate` nachholen.
|
||||
@@ -317,8 +322,10 @@ docker compose -f docker-compose.prod.yml logs -f db
|
||||
|
||||
**Gesunder Start sieht so aus:** `db` wird `healthy`, danach startet `api` und
|
||||
protokolliert die durchgelaufenen Prisma-Migrationen sowie zuletzt
|
||||
`Tessera API running on port 3001` (aus `apps/api/src/main.ts`). Erst danach startet
|
||||
`web`, weil `depends_on: api: condition: service_healthy` das erzwingt.
|
||||
`Tessera API running on port 3001` und direkt darunter eine Zeile wie
|
||||
`Tessera API v1.0.0 (live) abc1234` (beides aus `apps/api/src/main.ts`) – Version,
|
||||
Kanal und Kurzkennung des Standes, der gerade läuft (siehe Kapitel 9). Erst danach
|
||||
startet `web`, weil `depends_on: api: condition: service_healthy` das erzwingt.
|
||||
|
||||
| Symptom | Wahrscheinliche Ursache | Prüfen / Beheben |
|
||||
|---|---|---|
|
||||
@@ -342,5 +349,173 @@ Berechtigungen des `act_runner`-Docker-Socket-Mounts) aufgesetzt wird, ist bewus
|
||||
nicht Teil dieses Dokuments – das steht vollständig in
|
||||
[`docs/ci-cd-setup.md`](./ci-cd-setup.md). Die Grenze zwischen beiden Dokumenten:
|
||||
Sobald ein neues Image lokal vorliegt oder in einer Registry verfügbar ist, beginnt
|
||||
dieses Betriebshandbuch (Kapitel 4); alles davor – wie das Image entsteht – gehört
|
||||
in das CI/CD-Runbook.
|
||||
dieses Betriebshandbuch (Kapitel 4 und 9); alles davor – wie das Image entsteht –
|
||||
gehört in das CI/CD-Runbook.
|
||||
|
||||
## 9. Zwei Kanäle: Live und Beta
|
||||
|
||||
Seit September 2026 gibt es Tessera in zwei Ausgaben, die getrennt voneinander
|
||||
laufen. Dieses Kapitel erklärt, was das bedeutet, welche Zeile auf welchem Server
|
||||
stehen muss, wie eine Version freigegeben wird, wie ein dringender Fehler auf Live
|
||||
behoben wird, und wie Sie jederzeit sehen, welche Fassung gerade läuft.
|
||||
|
||||
### Was ein Kanal ist
|
||||
|
||||
Ein Kanal ist eine Ausgabe von Tessera, die auf einem bestimmten Server läuft und
|
||||
nach eigenen Regeln neue Stände bekommt. Es gibt zwei:
|
||||
|
||||
- **Beta** – alles Neue, sofort nach jeder Änderung. Läuft unter
|
||||
`alpha.tessera.ctl.de`. Das Etikett (die Kennzeichnung des Docker-Images in der
|
||||
Registry) heißt `beta`. Das ältere Etikett `latest` ist nur ein zweiter Name für
|
||||
genau dasselbe Beta-Image; es bleibt vorerst bestehen, damit nichts kaputtgeht,
|
||||
und kann später wegfallen.
|
||||
- **Live** – nur freigegebene Versionen mit einer Nummer. Läuft unter
|
||||
`tessera.ctl.de` auf dem neuen Server. Das Etikett heißt `live`; zusätzlich trägt
|
||||
jede freigegebene Version ihre Nummer als eigenes Etikett (`v1.0.0`, `v1.0.1`, …),
|
||||
damit man jederzeit auch einen älteren Stand gezielt holen kann.
|
||||
|
||||
Die Versionsnummer kommt aus der Freigabe (in Git heißt das „Tag“ – eine Markierung
|
||||
an einem bestimmten Stand), nicht aus einer Datei im Code. Zwischen zwei Freigaben
|
||||
zeigt die Beta eine Kennung wie `v1.0.0-12-gabc1234`: das bedeutet „12 Änderungen
|
||||
nach Version 1.0.0, Stand abc1234“. Vor der allerersten Freigabe steht dort nur die
|
||||
Kurzkennung des Standes (sieben Zeichen, z. B. `abc1234`).
|
||||
|
||||
### Die eine Zeile je Server
|
||||
|
||||
Welchen Kanal ein Server bekommt, entscheidet **eine einzige Zeile** in der Datei
|
||||
`/opt/tessera/.env`:
|
||||
|
||||
- auf **alpha** (Beta): `IMAGE_TAG=beta`
|
||||
- auf dem **neuen Live-Server**: `IMAGE_TAG=live`
|
||||
|
||||
Fehlt die Zeile ganz, nimmt die Compose-Datei von selbst `beta`. Für den Live-Server
|
||||
ist die Zeile also Pflicht, sonst zieht er die Beta.
|
||||
|
||||
Weil `/opt/tessera` keine Arbeitskopie des Repositorys ist (siehe Kapitel 3,
|
||||
„Konfigurationsdrift“), muss die Compose-Datei auf dem Server einmal von Hand
|
||||
angepasst werden. Auf alpha ist das die Datei `/opt/tessera/docker-compose.prod.yml`
|
||||
(die `.env` dort verweist mit `COMPOSE_FILE` auf sie). Zuerst eine Sicherung:
|
||||
|
||||
```bash
|
||||
cd /opt/tessera
|
||||
cp docker-compose.prod.yml docker-compose.prod.yml.bak.$(date +%Y%m%d)
|
||||
```
|
||||
|
||||
Dann die zwei `image:`-Zeilen (eine beim Dienst `web`, eine beim Dienst `api`) auf
|
||||
diese Form bringen – der einzige Unterschied zu heute ist das Ende der Zeile:
|
||||
|
||||
```yaml
|
||||
image: git.vicolab.de/schalli/tessera-ctl/web:${IMAGE_TAG:-beta}
|
||||
```
|
||||
|
||||
```yaml
|
||||
image: git.vicolab.de/schalli/tessera-ctl/api:${IMAGE_TAG:-beta}
|
||||
```
|
||||
|
||||
Danach wie in Kapitel 4:
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.prod.yml pull
|
||||
docker compose -f docker-compose.prod.yml up -d --force-recreate api web
|
||||
```
|
||||
|
||||
Hinweis: Die Vorlage `.env.prod.example` im Repository enthält die Zeile
|
||||
`IMAGE_TAG` noch nicht. Wer eine neue `.env` aus der Vorlage anlegt, ergänzt die
|
||||
Zeile von Hand.
|
||||
|
||||
### Eine Version freigeben
|
||||
|
||||
Das Freigeben erledigt Claude; Sie sagen nur „Version X freigeben“. Zur Einordnung,
|
||||
was dabei passiert:
|
||||
|
||||
```bash
|
||||
git checkout live
|
||||
git merge --ff-only main
|
||||
git tag -a vX.Y.Z -m "Tessera X.Y.Z"
|
||||
git push origin live vX.Y.Z
|
||||
```
|
||||
|
||||
Der zweite Befehl übernimmt den Stand der Beta in den Live-Zweig. Wenn er sich
|
||||
weigert, ist eine frühere Korrektur (siehe Hotfix, Schritt 5) noch nicht zurück in
|
||||
`main` – dann wird erst das nachgeholt. Der Push löst die Pipeline zweimal aus: der
|
||||
Zweig `live` wird nur geprüft, der Tag `vX.Y.Z` wird gebaut und als `live` und
|
||||
`vX.Y.Z` abgelegt. Das dauert etwa vier bis sechs Minuten.
|
||||
|
||||
Danach spielen Sie die Version auf dem Live-Server ein – Kapitel 4 gilt unverändert:
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.prod.yml pull
|
||||
docker compose -f docker-compose.prod.yml up -d --force-recreate api web
|
||||
```
|
||||
|
||||
**Erstfreigabe v1.0.0:** Den Zweig `live` gibt es noch nicht. Er entsteht beim
|
||||
ersten Mal aus `main` (`git checkout -b live main`), bekommt den Tag `v1.0.0` und
|
||||
wird zusammen mit dem Tag gepusht. Das erfolgt, sobald der Knopf „Fehler melden“
|
||||
eingebaut ist – nicht in diesem Durchlauf.
|
||||
|
||||
### Einen Fehler auf Live beheben (Hotfix)
|
||||
|
||||
Ein Hotfix ist eine kleine Korrektur, die auf Live landen muss, **ohne** die
|
||||
Neuerungen der Beta mitzunehmen. Ablauf (Claude führt die Git-Schritte aus, Sie
|
||||
spielen ein):
|
||||
|
||||
1. Den Live-Stand holen: `git checkout live && git pull`.
|
||||
2. Einen Korrekturzweig `hotfix/<kurzer-name>` von `live` anlegen.
|
||||
3. Die Korrektur machen und die Tests laufen lassen.
|
||||
4. Nach `live` mergen, die nächste Nummer vergeben (`vX.Y.(Z+1)`, also z. B.
|
||||
`v1.0.1` nach `v1.0.0`) und beides pushen: `git push origin live vX.Y.(Z+1)`.
|
||||
Danach spielen Sie die Version auf dem Live-Server ein (Befehle wie oben).
|
||||
5. Die Korrektur in die Beta übernehmen: `git checkout main && git merge live`.
|
||||
Vorher wird geprüft, ob die Korrektur dort noch zusammenpasst (Konflikte, Tests),
|
||||
dann `git push` – die Beta bekommt sie mit dem nächsten Pipeline-Lauf.
|
||||
|
||||
**Keine Datenbankänderung als Hotfix.** Der Grund in Alltagssprache:
|
||||
Datenbankänderungen (Migrationen) tragen einen Zeitstempel im Namen und werden in
|
||||
dieser Reihenfolge ausgeführt. Die Beta hat womöglich schon neuere Änderungen
|
||||
eingespielt. Eine Hotfix-Änderung mit noch späterem Zeitstempel landet beim
|
||||
Übernehmen in die Beta hinter Änderungen, die sie eigentlich nicht kennt – das ist
|
||||
der eine Fall, der beim Zusammenführen still kaputtgehen kann. Braucht eine Korrektur
|
||||
eine Datenbankänderung, wird sie als reguläre Version über `main` freigegeben.
|
||||
|
||||
### Woran Sie erkennen, welche Version läuft
|
||||
|
||||
Drei Wege, vom einfachsten zum genauesten:
|
||||
|
||||
1. **In der Oberfläche:** Unten in der Seitenleiste steht `v1.0.0 · Live` bzw.
|
||||
`v1.0.0-12-gabc1234 · Beta`. Wenn Sie die Maus darüber halten, erscheinen die
|
||||
Kurzkennung des Standes und die Version, die der Server meldet. Weichen
|
||||
Oberfläche und Server voneinander ab, wurde nur einer der beiden Container neu
|
||||
erstellt – dann Kapitel 4 anwenden (`--force-recreate api web`).
|
||||
2. **Auf dem Server per Abfrage:**
|
||||
|
||||
```bash
|
||||
curl -s http://localhost:3001/health/version
|
||||
```
|
||||
|
||||
Die Antwort enthält die Felder `version`, `channel` (`beta` oder `live`),
|
||||
`commit` (Kurzkennung) und `buildTime` (wann das Image gebaut wurde).
|
||||
3. **Im Protokoll:**
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.prod.yml logs api | grep "Tessera API"
|
||||
```
|
||||
|
||||
Zeigt die Startzeile `Tessera API v1.0.0 (live) abc1234` (siehe Kapitel 7).
|
||||
|
||||
### Den neuen Live-Server einrichten
|
||||
|
||||
Kapitel 2 gilt vollständig. Die Abweichungen gegenüber alpha:
|
||||
|
||||
- In der `.env` steht `IMAGE_TAG=live`.
|
||||
- Eigene, neu erzeugte Geheimnisse: `JWT_SECRET`, `TESSERA_ENCRYPTION_KEY`,
|
||||
`DB_PASSWORD` und das Admin-Passwort. Nichts davon von alpha übernehmen.
|
||||
- Eine eigene, leere Datenbank. Die API legt beim ersten Start den ersten Admin an
|
||||
(Kapitel 2, Schritt 4). Die alpha-Datenbank wird **nicht** kopiert – es sei denn,
|
||||
das wird ausdrücklich gewünscht. In diesem Fall gilt Kapitel 6 (Wiederherstellung)
|
||||
**und** der Live-Server muss denselben `TESSERA_ENCRYPTION_KEY` wie alpha
|
||||
bekommen, sonst sind alle gespeicherten Zugangsdaten unbrauchbar.
|
||||
- `APP_URL=https://tessera.ctl.de`.
|
||||
- Der erste `pull` holt das Etikett `live`. Vor der Erstfreigabe v1.0.0 gibt es
|
||||
dieses Etikett noch nicht – deshalb erst freigeben, dann installieren. Für einen
|
||||
Probelauf davor kann vorübergehend `IMAGE_TAG=beta` stehen; danach auf `live`
|
||||
umstellen und `pull` + `up -d --force-recreate api web` wiederholen.
|
||||
|
||||
+81
-19
@@ -80,11 +80,24 @@ docker ps --filter name=gitea-runner
|
||||
|
||||
### Gitea Secrets (fuer die CI-Pipeline)
|
||||
|
||||
In Gitea unter **Repository > Settings > Actions > Secrets** koennen Secrets
|
||||
fuer die Pipeline konfiguriert werden. Aktuell werden keine Secrets in der
|
||||
Pipeline benoetigt, da Images lokal gebaut und deployed werden (kein Registry-Push).
|
||||
In Gitea unter **Repository > Settings > Actions > Secrets** werden die Secrets
|
||||
fuer die Pipeline konfiguriert. Benoetigt wird genau eines:
|
||||
|
||||
Falls kuenftig Deploy-Pfade oder Credentials benoetigt werden:
|
||||
| Secret | Beschreibung |
|
||||
|--------|--------------|
|
||||
| `REGISTRY_TOKEN` | Gitea-Zugangstoken (Access Token) mit Schreibrecht auf Pakete (`package: write`). Wird im Job `publish` fuer `docker login localhost:3002 --password-stdin` verwendet. |
|
||||
|
||||
Das Token erscheint nie im Log: es wird per `--password-stdin` uebergeben und
|
||||
Gitea maskiert Secret-Werte in der Job-Ausgabe. Das Veroeffentlichungs-Skript
|
||||
`.gitea/scripts/publish-images.sh` kennt das Token nicht; der Login bleibt im
|
||||
Workflow.
|
||||
|
||||
Der Push geht ueber `localhost:3002` (Gitea laeuft auf demselben Rechner wie der
|
||||
Runner), weil der Nginx Proxy Manager vor `git.vicolab.de` grosse Image-Blobs
|
||||
blockt. Das Pullen auf den Servern laeuft ueber `git.vicolab.de`
|
||||
(`docker-compose.prod.yml`).
|
||||
|
||||
Weitere Secrets bei Bedarf:
|
||||
|
||||
1. In Gitea **Settings > Actions > Secrets** den Secret anlegen
|
||||
2. In `.gitea/workflows/ci.yml` ueber `${{ secrets.SECRET_NAME }}` referenzieren
|
||||
@@ -94,27 +107,62 @@ hardcoden.
|
||||
|
||||
## 4. Pipeline-Ueberblick
|
||||
|
||||
Die CI/CD-Pipeline (`.gitea/workflows/ci.yml`) wird bei jedem Push auf `main`
|
||||
ausgefuehrt und besteht aus drei aufeinander aufbauenden Jobs:
|
||||
Die CI/CD-Pipeline (`.gitea/workflows/ci.yml`) laeuft bei jedem Push auf die
|
||||
Zweige `main` und `live` sowie bei jedem Tag `v*` (z. B. `v1.0.0`) und besteht
|
||||
aus drei aufeinander aufbauenden Jobs:
|
||||
|
||||
1. **quality** -- Lint (Biome) und TypeScript Type-Check
|
||||
1. **quality** -- Lint und TypeScript Type-Check (Lint ist derzeit ein Leerlauf,
|
||||
siehe WINDOWS #35; der Type-Check ist echt)
|
||||
2. **test** -- Vitest Unit- und Integrationstests
|
||||
3. **build-deploy** -- Docker Images bauen und Services neu starten
|
||||
3. **publish** -- Docker Images mit Versionsstempel bauen und in die Gitea-Registry
|
||||
veroeffentlichen
|
||||
|
||||
Ablauf: `quality` -> `test` -> `build-deploy` (jeder Job nur bei Erfolg des
|
||||
vorherigen).
|
||||
Ablauf: `quality` -> `test` -> `publish` (jeder Job nur bei Erfolg des
|
||||
vorherigen). Der Job `publish` besteht aus drei Schritten: `actions/checkout@v4`
|
||||
mit `fetch-depth: 0` (volle Historie samt Tags, sonst liefert `git describe`
|
||||
nichts), Login in die Registry (siehe Abschnitt 3) und der Aufruf von
|
||||
`.gitea/scripts/publish-images.sh`.
|
||||
|
||||
### Kein Registry-Push
|
||||
### Zwei Kanaele: Etiketten je Anlass
|
||||
|
||||
Images werden **lokal auf dem Server gebaut** und nicht in eine Registry
|
||||
gepusht (D-13). Da der Runner und die Applikation auf demselben Server laufen,
|
||||
baut die Pipeline die Images direkt mit `docker compose build` und startet die
|
||||
Services mit `docker compose up -d` neu.
|
||||
Das Skript `.gitea/scripts/publish-images.sh` entscheidet allein anhand
|
||||
`GITHUB_REF`, ob und unter welchen Etiketten veroeffentlicht wird:
|
||||
|
||||
Vorteile:
|
||||
- Keine Registry-Infrastruktur noetig
|
||||
- Schnellerer Deploy (kein Push/Pull ueber Netzwerk)
|
||||
- Einfachere Konfiguration
|
||||
| Anlass | Kanal (`APP_CHANNEL`) | Etiketten in der Registry |
|
||||
|--------|----------------------|---------------------------|
|
||||
| Push auf `main` | `beta` | `beta` und `latest` (`latest` ist nur ein Alias fuer `beta` und entfaellt spaeter) |
|
||||
| Tag `vX.Y.Z` | `live` | `live` und `vX.Y.Z` |
|
||||
| Push auf `live` ohne Tag | -- | keine; der Lauf prueft nur (`quality`, `test`), das Skript endet mit "nichts zu tun" |
|
||||
|
||||
Das Kanalmodell fuer den Betrieb (welcher Server welches Etikett zieht, Freigabe,
|
||||
Hotfix) steht in `docs/anleitung-betrieb.md`, Kapitel 9.
|
||||
|
||||
### Versionsstempel
|
||||
|
||||
Das Skript berechnet vier Werte und gibt sie als `--build-arg` an beide
|
||||
Dockerfiles (`apps/web/Dockerfile`, `apps/api/Dockerfile`):
|
||||
|
||||
| Build-Arg | Quelle |
|
||||
|-----------|--------|
|
||||
| `APP_VERSION` | `git describe --tags --always` (ohne Tag: kurzer Commit-SHA) |
|
||||
| `APP_CHANNEL` | `beta` oder `live`, siehe Tabelle oben |
|
||||
| `APP_COMMIT` | `git rev-parse --short HEAD` |
|
||||
| `APP_BUILD_TIME` | `date -u`, ISO-Format |
|
||||
|
||||
Die API liest die Werte zur Laufzeit (`GET /health/version`, Startzeile im Log).
|
||||
Das Web-Image bettet `NEXT_PUBLIC_APP_*` beim Build in das Browser-Bundle ein --
|
||||
deshalb laeuft die `builder`-Stufe des Web-Images jetzt bei jedem Pipeline-Lauf
|
||||
neu, die Laufzeit liegt eher bei 4-6 statt 2 Minuten.
|
||||
|
||||
Lokale Probe ohne Docker-Aufruf:
|
||||
|
||||
```bash
|
||||
GITHUB_REF=refs/tags/v1.2.3 sh .gitea/scripts/publish-images.sh --print-plan
|
||||
```
|
||||
|
||||
Hinweis: Die fruehere Entscheidung D-13 (Images lokal bauen, keine Registry) ist
|
||||
ueberholt -- seit der Einfuehrung der Gitea-Registry werden Images gepusht und von
|
||||
den Servern per `docker compose pull` geholt.
|
||||
|
||||
## 5. Sicherheitshinweise
|
||||
|
||||
@@ -146,6 +194,12 @@ Workflow-Dateien in `.gitea/workflows/` werden direkt aus dem Repository
|
||||
geladen. Da nur vertrauenswuerdiger Code gepusht wird (D-11, Claude als
|
||||
einziger Committer), ist das Risiko einer manipulierten Pipeline minimal.
|
||||
|
||||
Ein Tag-Push `v*` ist der Freigabe-Hebel fuer Live: wer ihn setzen darf, kann
|
||||
das `live`-Etikett neu belegen. Heute hat nur das Konto `schalli` Schreibrecht
|
||||
(0 Kollaborateure, keine Branch-Regeln). Kommen weitere Konten dazu, in Gitea
|
||||
unter **Repository > Settings > Branches / Tags** eine Tag-Schutzregel fuer `v*`
|
||||
und einen Branch-Schutz fuer `live` anlegen (T-KU1-04).
|
||||
|
||||
## 6. Fehlerbehebung
|
||||
|
||||
### Runner registriert sich nicht
|
||||
@@ -167,3 +221,11 @@ einziger Committer), ist das Risiko einer manipulierten Pipeline minimal.
|
||||
erreichbar ist
|
||||
2. Docker Daemon Status pruefen: `docker info`
|
||||
3. Disk Space pruefen: `df -h`
|
||||
|
||||
### Stempel zeigt `dev` oder nur eine Kurzkennung statt des Tags
|
||||
|
||||
1. Im Job `publish` pruefen, dass `actions/checkout@v4` mit `fetch-depth: 0`
|
||||
auscheckt -- ohne Tags liefert `git describe --tags --always` nur den SHA
|
||||
2. Pruefen, ob der Tag wirklich gepusht wurde: `git ls-remote --tags origin`
|
||||
3. `dev` bedeutet: das Image wurde ohne Build-Args gebaut (lokal statt ueber
|
||||
das Skript) -- das ist fuer lokale Builds normal
|
||||
|
||||
Reference in New Issue
Block a user