#!/usr/bin/env bash set -euo pipefail here="$(cd "$(dirname "$0")" && pwd)" pre="$here/preflight.sh" tmp="$(mktemp -d)" listener="" trap '[ -n "$listener" ] && kill "$listener" 2>/dev/null; rm -rf "$tmp"' EXIT free_port() { python3 -c 'import socket; s=socket.socket(); s.bind(("127.0.0.1",0)); print(s.getsockname()[1])'; } port="$(free_port)" root="$tmp/root" mkdir -p "$root/deploy" "$root/dms/cmd/app" "$root/dms/migrations/tenant" "$tmp/units" printf 'dms\t%s\t%s\n' "$port" "$port" > "$root/deploy/ports.tsv" printf 'package main\nvar addr = ":%s"\n' "$port" > "$root/dms/cmd/app/main.go" touch "$root/dms/migrations/tenant/0001_documents.up.sql" export NEXARCH_PREFLIGHT_UNIT_DIR="$tmp/units" expect_fail() { if "$pre" "$@" >/dev/null 2>"$tmp/err"; then echo "FAIL: $1 nicht erkannt" >&2; exit 1; fi local want="${*: -1}" grep -q "$want" "$tmp/err" || { echo "FAIL: meldung fehlt ($want)" >&2; cat "$tmp/err" >&2; exit 1; } } run() { "$pre" "$@" >/dev/null 2>"$tmp/err" || { echo "FAIL: freies system abgelehnt" >&2; cat "$tmp/err" >&2; exit 1; }; } # Freies System besteht. run --skip-db --modules dms "$root" # Belegter Port: Meldung nennt Port und Modul. python3 -c "import socket,time; s=socket.socket(); s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1); s.bind(('127.0.0.1',$port)); s.listen(1); time.sleep(60)" & listener=$! for _ in $(seq 20); do (exec 3<>"/dev/tcp/127.0.0.1/$port") 2>/dev/null && break; sleep 0.1; done if "$pre" --skip-db --modules dms "$root" >/dev/null 2>"$tmp/err"; then echo "FAIL: belegter port nicht erkannt" >&2; exit 1; fi grep -q "port $port (dms" "$tmp/err" || { echo "FAIL: meldung ohne port/modul" >&2; cat "$tmp/err" >&2; exit 1; } # Bei --upgrade darf der eigene Dienst den Port halten. run --upgrade --skip-db --modules dms "$root" kill "$listener"; wait "$listener" 2>/dev/null || true; listener="" # Vorhandene Unit. touch "$tmp/units/nexarch-dms-worker.service" expect_fail --skip-db --modules dms "$root" "nexarch-dms-worker.service existiert bereits" run --upgrade --skip-db --modules dms "$root" rm "$tmp/units/nexarch-dms-worker.service" # Fehlende DB-Konfiguration ist ein Fehler, kein stilles Ueberspringen. env -u NEXARCH_DMS_APP_TENANT_DSN "$pre" --modules dms "$root" >/dev/null 2>"$tmp/err" && { echo "FAIL: fehlende DSN nicht erkannt" >&2; exit 1; } grep -q "DSN nicht gesetzt" "$tmp/err" || { echo "FAIL: DSN-meldung fehlt" >&2; exit 1; } # Datenbank-Pruefungen gegen echte PostgreSQL (nur mit TEST_TENANT_DSN). if [ -n "${TEST_TENANT_DSN:-}" ] && command -v psql >/dev/null 2>&1; then schema="preflight_$$_$RANDOM" psql "$TEST_TENANT_DSN" -qc "CREATE SCHEMA $schema" >/dev/null trap 'psql "$TEST_TENANT_DSN" -qc "DROP SCHEMA IF EXISTS $schema CASCADE" >/dev/null 2>&1; [ -n "$listener" ] && kill "$listener" 2>/dev/null; rm -rf "$tmp"' EXIT export PGOPTIONS="-c search_path=$schema" export NEXARCH_DMS_APP_TENANT_DSN="$TEST_TENANT_DSN" sql() { psql "$TEST_TENANT_DSN" -qc "$1" >/dev/null; } run --modules dms "$root" # leeres Schema sql "CREATE TABLE dms_schema_migrations (version TEXT PRIMARY KEY, applied_at TIMESTAMPTZ DEFAULT now())" run --modules dms "$root" # Tabelle leer sql "INSERT INTO dms_schema_migrations (version) VALUES ('0001_documents')" expect_fail --modules dms "$root" "bestehende Installation" run --upgrade --modules dms "$root" sql "INSERT INTO dms_schema_migrations (version) VALUES ('9999_fremd')" expect_fail --upgrade --modules dms "$root" "9999_fremd ist diesem Stand unbekannt" # Fremde generische schema_migrations stoert nicht (FDN-13). sql "DELETE FROM dms_schema_migrations WHERE version = '9999_fremd'; CREATE TABLE schema_migrations (version TEXT); INSERT INTO schema_migrations VALUES ('0001_core')" run --upgrade --modules dms "$root" NEXARCH_DMS_APP_TENANT_DSN="postgres://nobody@127.0.0.1:1/none?connect_timeout=2" expect_fail --modules dms "$root" "nicht erreichbar" else echo "hinweis: DB-pruefungen uebersprungen (TEST_TENANT_DSN/psql fehlt)" fi echo "preflight_test ok"