Phase 11: Freigabereife
Kein Modul, sondern die drei Software-Voraussetzungen fuer 1.0.0: Auskunft nach Art. 15 DSGVO, ein geprueftes Sicherungskonzept und eine Pipeline. Das Auskunftsrecht war ein Versprechen ohne Umsetzung: `person.export` stand seit Phase 0 im Katalog und war dem Kommandanten zugewiesen, implementiert war nichts. Ohne Auskunftsseite ist ein Loeschkonzept nicht abnehmbar. Jetzt sammelt FLORIAN dreizehn Abschnitte ueber eine Person, mit dem Zweck ueber jedem - Art. 15 verlangt nicht nur die Daten, sondern auch Zwecke und Rechte, und eine blosse Liste erfuellt die Pflicht nicht. Ein Durchgang liefert Anzeige, PDF und JSON nach Art. 20. Die Trennlinie ist "ueber mich" gegen "von mir": was ueber die Person gespeichert ist, steht vollstaendig drin, auch das Unangenehme. Was sie getan hat, steht als Zahl drin - die Pruefprotokolle gehoeren zum Nachweisbestand der Wehr, und vollstaendig ausgeliefert kaeme jeder ueber eine Selbstauskunft an die Geraeteakten. Die Rueckspielprobe hat sich sofort bezahlt gemacht: der erste Versuch lief sauber durch und hatte dabei saemtliche Unveraenderlichkeitsgarantien der Datenbank entfernt. Die Vorgabeprivilegierung aus dem Init-Skript gibt jeder von pg_restore neu angelegten Tabelle wieder alle Rechte, und GRANT kann nur hinzufuegen. Die Anwendungsrolle durfte danach das Audit-Log aendern, Wiki-Fassungen loeschen, Kiosk-Vorgaenge umschreiben - und nichts haette darauf hingewiesen. Gefunden haben es vier Datenbanktests unmittelbar nach der Probe, also genau die Probe, wegen der 1.0.0 sie verlangt. Die Pipeline ist geschrieben, aber NICHT erprobt: in Gitea ist kein act_runner registriert. Das steht so im README und im Devlog, damit sich niemand auf eine Pruefung verlaesst, die nicht stattfindet. 601 Unit-Tests gruen; Sicherung und Wiederherstellung einmal vollstaendig durchgefuehrt und die Tests danach erneut gruen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
91742a0dd7
commit
9156dcc144
@@ -0,0 +1,184 @@
|
||||
# =============================================================================
|
||||
# Die Pruefung bei jedem Push.
|
||||
#
|
||||
# Bis Phase 10 gab es 581 Unit- und 266 E2E-Tests — und nichts, was sie
|
||||
# ausfuehrte ausser einem Menschen, der daran dachte. In der Sitzung, in der
|
||||
# die Kassenverwaltung entstand, haben die Tests vier echte Fehler gefunden,
|
||||
# zwei davon in Code, der eine Stunde alt war. Genau das soll hier von allein
|
||||
# passieren.
|
||||
#
|
||||
# Zwei Auftraege, bewusst getrennt:
|
||||
#
|
||||
# pruefung typecheck, lint und die Unit-Tests. Braucht eine Datenbank,
|
||||
# weil ein Teil der Tests die Trigger und RLS gegen echtes
|
||||
# Postgres prueft — mit einer Attrappe waeren sie wertlos.
|
||||
#
|
||||
# oberflaeche die E2E-Tests. Dauern eine Dreiviertelstunde und brauchen den
|
||||
# halben Stack, deshalb laufen sie nur auf main und in Pull
|
||||
# Requests, nicht bei jedem Zwischenstand auf einem Zweig.
|
||||
# =============================================================================
|
||||
name: Pruefung
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
# Dieselben Werte wie in .env.example. Es sind Testdaten in einem
|
||||
# Wegwerf-Container; echte Geheimnisse haben in einer Pipeline nichts zu
|
||||
# suchen und stehen im Betrieb in der .env.
|
||||
POSTGRES_USER: florian
|
||||
POSTGRES_PASSWORD: pruefung
|
||||
POSTGRES_DB: florian
|
||||
POSTGRES_APP_PASSWORD: pruefung_app
|
||||
DATABASE_URL: postgresql://florian_app:pruefung_app@localhost:5432/florian?schema=public
|
||||
DIRECT_DATABASE_URL: postgresql://florian:pruefung@localhost:5432/florian?schema=public
|
||||
AUTH_SECRET: nur-fuer-die-pruefung-nicht-fuer-den-betrieb
|
||||
AUTH_TRUST_HOST: "true"
|
||||
APP_URL: http://localhost:3100
|
||||
S3_ENDPOINT: localhost
|
||||
S3_PORT: "9000"
|
||||
S3_USE_SSL: "false"
|
||||
S3_ACCESS_KEY: florian
|
||||
S3_SECRET_KEY: pruefung_minio
|
||||
S3_BUCKET: florian
|
||||
REDIS_URL: redis://localhost:6379
|
||||
TZ: Europe/Berlin
|
||||
|
||||
jobs:
|
||||
pruefung:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: npm
|
||||
|
||||
# Das eigene Postgres-Image statt eines fertigen: FLORIAN braucht
|
||||
# PostGIS **und** pgvector, und kein oeffentliches Image bringt beides
|
||||
# mit. Ein Dienst-Container mit postgres:17 wuerde die Migrationen
|
||||
# durchlassen und erst bei der ersten Umkreissuche scheitern.
|
||||
- name: Datenbank bauen und starten
|
||||
run: |
|
||||
docker build -t florian-postgres:pruefung ./docker/postgres
|
||||
docker run -d --name postgres -p 5432:5432 \
|
||||
-e POSTGRES_USER=$POSTGRES_USER \
|
||||
-e POSTGRES_PASSWORD=$POSTGRES_PASSWORD \
|
||||
-e POSTGRES_DB=$POSTGRES_DB \
|
||||
-e POSTGRES_APP_PASSWORD=$POSTGRES_APP_PASSWORD \
|
||||
-e POSTGRES_INITDB_ARGS="--locale-provider=icu --icu-locale=de-DE --locale=C.UTF-8 --encoding=UTF8" \
|
||||
-v "$(pwd)/docker/postgres:/docker-entrypoint-initdb.d:ro" \
|
||||
florian-postgres:pruefung
|
||||
|
||||
- name: Redis und MinIO starten
|
||||
run: |
|
||||
docker run -d --name redis -p 6379:6379 redis:7-alpine
|
||||
docker run -d --name minio -p 9000:9000 \
|
||||
-e MINIO_ROOT_USER=$S3_ACCESS_KEY \
|
||||
-e MINIO_ROOT_PASSWORD=$S3_SECRET_KEY \
|
||||
minio/minio:latest server /data
|
||||
|
||||
- run: npm ci
|
||||
|
||||
- name: Auf die Datenbank warten
|
||||
run: |
|
||||
for i in $(seq 1 60); do
|
||||
docker exec postgres pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB" && exit 0
|
||||
sleep 2
|
||||
done
|
||||
echo "Postgres kam nicht hoch:"
|
||||
docker logs postgres
|
||||
exit 1
|
||||
|
||||
- run: npx prisma generate
|
||||
- run: npm run typecheck
|
||||
- run: npm run lint
|
||||
|
||||
- name: Migrationen einspielen
|
||||
run: npm run db:migrate
|
||||
|
||||
# Der Seed gehoert dazu: er ist selbst ein Test. Faellt eine Migration
|
||||
# oder ein Standardwert um, merkt man es hier und nicht erst, wenn eine
|
||||
# Wehr ihn zum ersten Mal ausfuehrt.
|
||||
- name: Beispielbestand anlegen
|
||||
run: npm run db:seed
|
||||
|
||||
- run: npm run test
|
||||
|
||||
- name: Aufraeumen
|
||||
if: always()
|
||||
run: docker rm -f postgres redis minio || true
|
||||
|
||||
oberflaeche:
|
||||
runs-on: ubuntu-latest
|
||||
# Nur wo es sich lohnt: ein voller Lauf dauert etwa 45 Minuten.
|
||||
if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: npm
|
||||
|
||||
- name: Dienste starten
|
||||
run: |
|
||||
docker build -t florian-postgres:pruefung ./docker/postgres
|
||||
docker run -d --name postgres -p 5432:5432 \
|
||||
-e POSTGRES_USER=$POSTGRES_USER \
|
||||
-e POSTGRES_PASSWORD=$POSTGRES_PASSWORD \
|
||||
-e POSTGRES_DB=$POSTGRES_DB \
|
||||
-e POSTGRES_APP_PASSWORD=$POSTGRES_APP_PASSWORD \
|
||||
-e POSTGRES_INITDB_ARGS="--locale-provider=icu --icu-locale=de-DE --locale=C.UTF-8 --encoding=UTF8" \
|
||||
-v "$(pwd)/docker/postgres:/docker-entrypoint-initdb.d:ro" \
|
||||
florian-postgres:pruefung
|
||||
docker run -d --name redis -p 6379:6379 redis:7-alpine
|
||||
docker run -d --name minio -p 9000:9000 \
|
||||
-e MINIO_ROOT_USER=$S3_ACCESS_KEY \
|
||||
-e MINIO_ROOT_PASSWORD=$S3_SECRET_KEY \
|
||||
minio/minio:latest server /data
|
||||
docker run -d --name gotenberg -p 3001:3000 gotenberg/gotenberg:8
|
||||
|
||||
- run: npm ci
|
||||
- run: npx playwright install --with-deps chromium
|
||||
|
||||
- name: Auf die Datenbank warten
|
||||
run: |
|
||||
for i in $(seq 1 60); do
|
||||
docker exec postgres pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB" && exit 0
|
||||
sleep 2
|
||||
done
|
||||
docker logs postgres
|
||||
exit 1
|
||||
|
||||
- run: npx prisma generate
|
||||
- run: npm run db:migrate
|
||||
|
||||
# Die E2E-Tests laufen seit Phase 8 gegen eine eigene Wehr, nicht gegen
|
||||
# den Beispielbestand. Das Skript legt beide an.
|
||||
- name: Testwehr anlegen
|
||||
run: npm run db:test-reset
|
||||
|
||||
- run: npm run build
|
||||
- run: npx playwright test
|
||||
env:
|
||||
GOTENBERG_URL: http://localhost:3001
|
||||
|
||||
- name: Fehlerbilder sichern
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: playwright-bericht
|
||||
path: |
|
||||
playwright-report/
|
||||
test-results/
|
||||
retention-days: 7
|
||||
|
||||
- name: Aufraeumen
|
||||
if: always()
|
||||
run: docker rm -f postgres redis minio gotenberg || true
|
||||
Reference in New Issue
Block a user