Files
Cibello-app/infrastructure/deployment/RUNBOOK.md
T
Claude d3f93a6f46 fix(ops): tools-image kopierar infrastructure/migrations sa db:migrate hittar journalen
- Dockerfile.tools: COPY infrastructure/migrations (migrate.ts laste /build/infrastructure/migrations men mappen saknades -> 'Cant find meta/_journal.json').
- RUNBOOK: nollstall anvandare med DELETE FROM users (respekterar creator_user_id ON DELETE SET NULL), aldrig TRUNCATE CASCADE.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-22 21:24:37 +00:00

144 lines
5.5 KiB
Markdown

# Cibello — drift & uppdaterings-runbook
Så uppdaterar vi prod **säkert och repeterbart**. Gäller EC2 `cibello-prod-app`
(eu-north-1). Koden hämtas från Gitea (`git.aamos.systems/platform-admin/Cibello-app`,
gren `master`) via en **read-only** deploy-koppling. Secrets (`.env`, `secrets/*.env`)
är otrackade i git och rörs aldrig.
## Karta
| Del | Var |
|-----|-----|
| Kod på servern | `/opt/cibello-platform` (symlänk `/opt/app-platform`) |
| Compose | `infrastructure/docker/docker-compose.production.yml` |
| Tjänster | `app-api` (:4100→4000), `app-worker`, `app-admin` (:4180→8080), `app-redis` |
| Ops-container | `app-tools` (profile `tools`, startar ej med `up`) — migrera/seed |
| Databas | RDS Postgres 16, databas `cibello` |
Kör docker-kommandon som root (eller `sudo`). Git körs som ägaren `ubuntu`.
Nedan förkortas `-f infrastructure/docker/docker-compose.production.yml` till `-f $C`.
---
## 1. Vanlig uppdatering (buggfix / ny funktion / ändrad kod)
**På din maskin:** committa och pusha till Gitea `master`.
**På servern:** ett kommando — hämtar, bygger, migrerar, startar om, healthcheckar,
och **rullar tillbaka automatiskt** om API:t inte svarar:
```bash
sudo bash /opt/cibello-platform/infrastructure/deployment/deploy.sh
```
Klart när det står `DEPLOY KLAR: <sha> (healthz OK)`.
---
## 2. Lägga till / uppdatera recept (och andra seed-data)
Recept, ingredienser och översättningar ligger i `packages/database/src/seed/data/`.
Seed är **idempotent** (upsert) och **rör aldrig `users`** — den lägger bara till/uppdaterar
katalogen. Den kan aldrig radera prod-data (TRUNCATE kräver `--test` + databasnamn som
slutar på `_test`; prod heter `cibello`).
1. Uppdatera seed-datan i repot, committa, pusha till Gitea.
2. Kör en vanlig deploy (steg 1) så koden är i synk.
3. Kör seed via tools-containern:
```bash
C=/opt/cibello-platform/infrastructure/docker/docker-compose.production.yml
sudo docker compose -f "$C" build app-tools
sudo docker compose -f "$C" --profile tools run --rm app-tools \
tsx packages/database/src/seed/run.ts
```
4. Verifiera antal (ändrar inget):
```bash
sudo docker exec -i app-api node -e 'const{Client}=require("pg");const u=(process.env.DATABASE_URL||"").replace(/[?&]sslmode=[^&]+/g,"").replace(/\?$/,"");const c=new Client({connectionString:u,ssl:/localhost|127\.0\.0\.1/.test(u)?false:{rejectUnauthorized:false}});c.connect().then(()=>c.query("select (select count(*) from recipes) recipes,(select count(*) from canonical_ingredients) ingredients,(select count(*) from users) users")).then(r=>{console.log(r.rows[0]);return c.end()}).catch(e=>{console.error(e.message);process.exit(1)})'
```
> **Rekommendation:** ta en RDS-snapshot före en stor seed, som extra skyddsnät.
---
## 3. Lägga till ett nytt språk
i18n-verktygen finns i `apps/mobile/scripts/` och `apps/worker/scripts/`
(`i18n-add-language`, `translate-recipes`, `verify-translations` m.fl.).
1. Kör i18n-add-language för det nya språket, generera + verifiera översättningar lokalt.
2. Committa (locale-filer + ev. `recipe_translations`/`ingredient_translations`-seed), pusha.
3. Deploy (steg 1) + seed (steg 2) så översättningarna hamnar i prod-DB.
4. Mobilappen: släpp en ny build med det nya språket (App Store / Google Play).
---
## 4. Schema-ändringar (migreringar)
Migreringar körs **automatiskt i `deploy.sh`** (steg 1) via tools-containern.
`migrate.ts` applicerar bara journal-poster nyare än det som redan är kört — klart no-op
om inget nytt finns, och rör bara schema, aldrig data.
Kör en migrering separat (utan full deploy):
```bash
C=/opt/cibello-platform/infrastructure/docker/docker-compose.production.yml
sudo docker compose -f "$C" build app-tools
sudo docker compose -f "$C" --profile tools run --rm app-tools \
tsx packages/database/src/migrate.ts
```
> **Alltid RDS-snapshot före migreringar** som lägger till/ändrar kolumner.
---
## 5. Admin-panelen
Admin byggs **inte** av `deploy.sh` (den har en build-arg `VITE_API_BASE_URL` som bakas
in vid bygget). Bygg om admin separat när dess kod ändras:
```bash
C=/opt/cibello-platform/infrastructure/docker/docker-compose.production.yml
sudo docker compose -f "$C" build app-admin # build-arg sätts i compose till https://api.cibello.app
sudo docker compose -f "$C" up -d app-admin
```
---
## 6. Rollback
`deploy.sh` rullar tillbaka **automatiskt** om healthz inte svarar efter en deploy.
Manuell rollback till föregående commit:
```bash
sudo -H -u ubuntu git -C /opt/cibello-platform reset --hard <föregående-sha>
C=/opt/cibello-platform/infrastructure/docker/docker-compose.production.yml
sudo docker compose -f "$C" build app-api app-worker
sudo docker compose -f "$C" up -d app-api app-worker
```
Databas: återställ från RDS-snapshot (konsolen) om en migrering behöver rullas tillbaka.
---
## 7. Snabb hälsokoll
```bash
curl -s -o /dev/null -w "internt: %{http_code}\n" http://127.0.0.1:4100/healthz
curl -s -o /dev/null -w "externt: %{http_code}\n" https://api.cibello.app/healthz
sudo docker compose -f /opt/cibello-platform/infrastructure/docker/docker-compose.production.yml ps
```
---
## 8. Nollställa användardata (försiktigt)
Använd **`DELETE FROM users`**, aldrig `TRUNCATE users CASCADE`. Recept har en FK
`creator_user_id → users` med `ON DELETE SET NULL`: `DELETE` respekterar det och
**behåller receptkatalogen** (nollställer bara skaparen), medan `TRUNCATE ... CASCADE`
ignorerar `SET NULL` och sveper med hela recept-tabellen. Ta alltid en RDS-snapshot
först, och kör SQL:en via samma `docker exec app-api node`-mönster som db-koll-scripten.