#!/usr/bin/env bash # Preview container entrypoint (flotilla SPEC §15). # # 1. Render nginx against Cloud Run's $PORT. # 2. Start the single-process uvicorn (which runs DB migrations on startup via # the app lifespan — §4.2: one process, one SQLite file, never scale workers). # 3. On a brand-new DB, apply the SYNTHETIC seed fixture so the preview shows # realistic content with no real user PII (§15). # 4. Hand the foreground to nginx. # # This is preview-only plumbing — production runs uvicorn under systemd and nginx # under the OS, never this script. set -euo pipefail : "${PORT:=8080}" : "${DATABASE_PATH:=/opt/rfc-app/backend/data/rfc-app.db}" export PORT DATABASE_PATH mkdir -p "$(dirname "$DATABASE_PATH")" # Render the nginx config with the injected port. envsubst '${PORT}' \ < /opt/rfc-app/deploy/preview/nginx.conf.template \ > /etc/nginx/nginx.conf fresh=0 [ -f "$DATABASE_PATH" ] || fresh=1 # Start uvicorn (backgrounded); the app's lifespan runs migrations on boot. cd /opt/rfc-app/backend uvicorn app.main:app --host 127.0.0.1 --port 8000 & UVICORN_PID=$! # Seed synthetic data once the schema exists (only on a fresh DB). if [ "$fresh" = "1" ]; then for _ in $(seq 1 30); do if [ -f "$DATABASE_PATH" ] \ && sqlite3 "$DATABASE_PATH" "SELECT 1 FROM schema_migrations LIMIT 1;" >/dev/null 2>&1; then break fi sleep 1 done if sqlite3 "$DATABASE_PATH" < /opt/rfc-app/deploy/preview/seed.sql; then echo "[preview-entrypoint] applied synthetic seed" >&2 else # Best-effort: a seed that drifts from the schema must not block the # preview from booting (it still serves /api/health + an empty app). echo "[preview-entrypoint] WARNING: synthetic seed failed (schema drift?) — continuing" >&2 fi fi # nginx in the foreground becomes the container's main process. (uvicorn is a # reparented child; for an ephemeral preview the hard stop on instance teardown # is fine — a process supervisor is a follow-up if graceful drain matters.) exec nginx -g 'daemon off;'