135 lines
3.3 KiB
Bash
135 lines
3.3 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
ROOT="${MOBILITY_WORKBENCH_ROOT:-/mnt/DATA/git/meubility-workbench}"
|
|
PYTHON="${PYTHON:-$ROOT/.venv/bin/python}"
|
|
HOST="${MOBILITY_HOST:-127.0.0.1}"
|
|
PORT="${MOBILITY_PORT:-8000}"
|
|
OPEN_BROWSER="${OPEN_BROWSER:-1}"
|
|
SAMPLE_MODE="${MOBILITY_SAMPLE_MODE:-missing}" # missing, always, never
|
|
|
|
LOG_DIR="$ROOT/data/dev-launcher"
|
|
SERVER_LOG="$LOG_DIR/server.log"
|
|
URL="http://$HOST:$PORT"
|
|
|
|
server_pid=""
|
|
|
|
fail() {
|
|
printf 'launch-dev: %s\n' "$*" >&2
|
|
exit 1
|
|
}
|
|
|
|
port_is_free() {
|
|
"$PYTHON" - "$1" "$2" <<'PY'
|
|
import socket
|
|
import sys
|
|
|
|
host = sys.argv[1]
|
|
port = int(sys.argv[2])
|
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
try:
|
|
sock.bind((host, port))
|
|
except OSError:
|
|
raise SystemExit(1)
|
|
PY
|
|
}
|
|
|
|
wait_for_url() {
|
|
"$PYTHON" - "$1" <<'PY'
|
|
import sys
|
|
import time
|
|
import urllib.request
|
|
|
|
url = sys.argv[1]
|
|
deadline = time.monotonic() + 60
|
|
last_error = None
|
|
while time.monotonic() < deadline:
|
|
try:
|
|
with urllib.request.urlopen(url, timeout=2) as response:
|
|
if 200 <= response.status < 500:
|
|
raise SystemExit(0)
|
|
except Exception as exc: # noqa: BLE001 - printed only on timeout.
|
|
last_error = exc
|
|
time.sleep(1)
|
|
print(f"Timed out waiting for {url}: {last_error}", file=sys.stderr)
|
|
raise SystemExit(1)
|
|
PY
|
|
}
|
|
|
|
configured_database() {
|
|
"$PYTHON" - <<'PY'
|
|
from app.config import settings
|
|
|
|
kind = "sqlite" if settings.is_sqlite_database else "postgresql" if settings.is_postgresql_database else "other"
|
|
print(f"{kind}\t{settings.database_url}")
|
|
PY
|
|
}
|
|
|
|
cleanup() {
|
|
if [ -n "${server_pid:-}" ] && kill -0 "$server_pid" 2>/dev/null; then
|
|
kill "$server_pid" 2>/dev/null || true
|
|
fi
|
|
}
|
|
trap cleanup EXIT INT TERM
|
|
|
|
[ -x "$PYTHON" ] || fail "Python virtualenv not found at $PYTHON. Run: cd $ROOT && python -m venv .venv && . .venv/bin/activate && pip install -r requirements.txt"
|
|
|
|
mkdir -p "$LOG_DIR"
|
|
: > "$SERVER_LOG"
|
|
|
|
port_is_free "$HOST" "$PORT" || fail "$URL is already in use"
|
|
|
|
cd "$ROOT"
|
|
db_info="$(configured_database)"
|
|
db_kind="$(printf '%s' "$db_info" | cut -f1)"
|
|
db_url="$(printf '%s' "$db_info" | cut -f2-)"
|
|
case "$SAMPLE_MODE" in
|
|
always)
|
|
printf 'Loading sample project. This clears project data in the configured database.\n'
|
|
"$PYTHON" -m app.cli load-sample
|
|
;;
|
|
missing)
|
|
if [ "$db_kind" = "sqlite" ] && [ "$db_url" = "sqlite:///./data/workbench.sqlite" ] && [ ! -s "$ROOT/data/workbench.sqlite" ]; then
|
|
printf 'Default SQLite database is missing. Loading sample project.\n'
|
|
"$PYTHON" -m app.cli load-sample
|
|
else
|
|
"$PYTHON" -m app.cli init-db
|
|
fi
|
|
;;
|
|
never)
|
|
"$PYTHON" -m app.cli init-db
|
|
;;
|
|
*)
|
|
fail "MOBILITY_SAMPLE_MODE must be missing, always, or never"
|
|
;;
|
|
esac
|
|
|
|
printf 'Starting Mobility Workbench at %s\n' "$URL"
|
|
"$PYTHON" -m uvicorn app.main:app --host "$HOST" --port "$PORT" --reload >"$SERVER_LOG" 2>&1 &
|
|
server_pid="$!"
|
|
|
|
printf 'Waiting for %s\n' "$URL"
|
|
wait_for_url "$URL" || {
|
|
tail -n 80 "$SERVER_LOG" >&2 || true
|
|
fail "server did not become reachable"
|
|
}
|
|
|
|
if [ "$OPEN_BROWSER" = "1" ] && command -v xdg-open >/dev/null 2>&1; then
|
|
xdg-open "$URL" >/dev/null 2>&1 || true
|
|
fi
|
|
|
|
cat <<EOF
|
|
|
|
Mobility Workbench is running.
|
|
Web UI: $URL
|
|
API: $URL/api
|
|
|
|
Log:
|
|
$SERVER_LOG
|
|
|
|
Press Ctrl+C to stop the server.
|
|
EOF
|
|
|
|
wait "$server_pid"
|