Files
AfiS-Aktensystem/start.sh
T
Harlekin e0b03ea336
Prüfung / Lint, Typen, Tests (push) Canceled after 0s
Prüfung / Images bauen (pdf) (push) Canceled after 0s
Prüfung / Images bauen (web) (push) Canceled after 0s
Prüfung / Images bauen (worker) (push) Canceled after 0s
Images / bauen (pdf, docker/pdf.Dockerfile) (push) Canceled after 0s
Images / bauen (web, docker/web.Dockerfile) (push) Canceled after 0s
Images / bauen (worker, docker/worker.Dockerfile) (push) Canceled after 0s
Gedankenstriche durch Bindestriche ersetzt
375 Vorkommen in 210 Dateien. Betrifft Kommentare, Oberflaechentexte und die
README; an keiner Stelle Bedeutung, nur Zeichensetzung.
2026-09-04 08:54:52 +02:00

142 lines
4.9 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# Startet die Anwendung für die lokale Entwicklung: Datenbank, Worker, Web.
#
# Das hier ist ausdrücklich **nicht** der Betrieb. Im Betrieb läuft alles als
# ein Dockge-Stack, siehe docs/11-betrieb.md. Dieses Skript ist für den Fall,
# dass der Stack gerade nicht läuft und man am Code arbeiten will.
#
# ./start.sh Datenbank, Worker und Web starten
# ./start.sh --ohne-worker nur Datenbank und Web (kein Discord nötig)
# ./start.sh --nur-db nur die Datenbank hochfahren
#
# Beenden mit Strg+C, das nimmt alle Kindprozesse mit.
set -euo pipefail
cd "$(dirname "$0")"
DB_CONTAINER="afis-dev-db"
DB_PORT="${AFIS_DB_PORT:-5434}"
DB_IMAGE="postgres:16-alpine"
MIT_WORKER=1
NUR_DB=0
for arg in "$@"; do
case "$arg" in
--ohne-worker) MIT_WORKER=0 ;;
--nur-db) NUR_DB=1 ;;
-h|--help) awk 'NR>1 && /^#/ { sub(/^# ?/, ""); print; next } NR>1 { exit }' "$0"; exit 0 ;;
*) echo "Unbekannte Option: $arg" >&2; exit 2 ;;
esac
done
info() { printf '\033[36m▸\033[0m %s\n' "$*"; }
warn() { printf '\033[33m!\033[0m %s\n' "$*"; }
fehler() { printf '\033[31m✗\033[0m %s\n' "$*" >&2; exit 1; }
# --- Node aus nvm holen, falls es nicht schon im PATH liegt -------------------
if ! command -v node >/dev/null 2>&1; then
if [ -s "$HOME/.nvm/nvm.sh" ]; then
# shellcheck disable=SC1091
. "$HOME/.nvm/nvm.sh" >/dev/null
nvm use --lts >/dev/null 2>&1 || nvm use node >/dev/null 2>&1 || true
fi
fi
command -v node >/dev/null 2>&1 || fehler "Node nicht gefunden. Node 22 installieren oder nvm laden."
if ! command -v pnpm >/dev/null 2>&1; then
corepack enable >/dev/null 2>&1 || true
fi
command -v pnpm >/dev/null 2>&1 || fehler "pnpm nicht gefunden. 'corepack enable' ausführen."
command -v docker >/dev/null 2>&1 || fehler "Docker nicht gefunden, die Datenbank läuft im Container."
[ -f .env ] || fehler ".env fehlt. Von .env.example abschreiben und die Discord-Werte eintragen."
# --- Datenbank ---------------------------------------------------------------
if [ -n "$(docker ps -q -f "name=^${DB_CONTAINER}$")" ]; then
info "Datenbank läuft bereits"
elif [ -n "$(docker ps -aq -f "name=^${DB_CONTAINER}$")" ]; then
info "Datenbank starten"
docker start "$DB_CONTAINER" >/dev/null
else
info "Datenbank anlegen (Port ${DB_PORT})"
docker run -d --name "$DB_CONTAINER" \
-e POSTGRES_DB=afis -e POSTGRES_USER=afis -e POSTGRES_PASSWORD=afis \
-p "${DB_PORT}:5432" "$DB_IMAGE" >/dev/null \
|| fehler "Container nicht gestartet. Läuft schon etwas auf Port ${DB_PORT}?"
fi
printf ' warte auf Postgres'
for _ in $(seq 1 60); do
if docker exec "$DB_CONTAINER" pg_isready -U afis -d afis >/dev/null 2>&1; then
printf ' bereit\n'
break
fi
printf '.'
sleep 1
done
docker exec "$DB_CONTAINER" pg_isready -U afis -d afis >/dev/null 2>&1 \
|| fehler "Postgres antwortet nicht."
# --- Schema und Grundzustand -------------------------------------------------
info "Prisma-Client erzeugen"
pnpm --filter @afis/db run build >/dev/null
info "Migrationen anwenden"
pnpm db:deploy >/dev/null
info "Grundzustand einspielen"
pnpm db:seed >/dev/null
# --- Dateiablage -------------------------------------------------------------
# Im Stack ist das ein Volume, hier ein Verzeichnis. Ohne es scheitert der
# erste Upload mit einem Fehler, der nichts erklärt.
FILES_DIR_LOKAL="$(grep -E '^FILES_DIR=' .env 2>/dev/null | cut -d= -f2- || true)"
FILES_DIR_LOKAL="${FILES_DIR_LOKAL:-/tmp/afis-files}"
mkdir -p "${FILES_DIR_LOKAL}/quarantine" "${FILES_DIR_LOKAL}/store"
info "Dateiablage unter ${FILES_DIR_LOKAL}"
# Die Prüfkette braucht beides. Fehlt eines, bleiben die betroffenen Uploads in
# der Quarantäne - sie gehen nicht ungeprüft durch. Siehe docs/07.
CLAMAV_SOCKET_LOKAL="$(grep -E '^CLAMAV_SOCKET=' .env 2>/dev/null | cut -d= -f2- || true)"
[ -S "${CLAMAV_SOCKET_LOKAL:-/var/run/clamav/clamd.sock}" ] \
|| warn "Kein clamd erreichbar: Uploads landen auf 'Prüfung unvollständig' und brauchen die Freigabe von Hand"
command -v qpdf >/dev/null \
|| warn "qpdf fehlt: PDF-Uploads landen auf 'Prüfung unvollständig' (im Container ist es enthalten)"
if [ "$NUR_DB" = "1" ]; then
info "Datenbank läuft auf localhost:${DB_PORT}. Beenden mit: docker stop ${DB_CONTAINER}"
exit 0
fi
# --- Kindprozesse ------------------------------------------------------------
PIDS=()
aufraeumen() {
echo
info "Beenden"
for pid in "${PIDS[@]:-}"; do
kill "$pid" 2>/dev/null || true
done
wait 2>/dev/null || true
info "Die Datenbank läuft weiter. Anhalten mit: docker stop ${DB_CONTAINER}"
}
trap aufraeumen INT TERM EXIT
if [ "$MIT_WORKER" = "1" ]; then
info "Worker starten (Discord-Rollenabgleich)"
pnpm worker:dev 2>&1 | sed 's/^/[worker] /' &
PIDS+=($!)
fi
info "Web starten"
pnpm dev 2>&1 | sed 's/^/[web] /' &
PIDS+=($!)
echo
info "Anwendung unter http://localhost:3000"
[ "$MIT_WORKER" = "1" ] || warn "Ohne Worker: Rollen werden nicht abgeglichen, /api/health meldet das Gateway als gestört"
echo
wait