launch-uvicorn-dev
Rama main · réplica de lectura del repositorio original.
#!/usr/bin/env bash
# Robot Dev Team Project
# File: launch-uvicorn-dev
# Description: Launch the FastAPI app via uvicorn using the local virtualenv.
# License: MIT
# SPDX-License-Identifier: MIT
# Copyright (c) 2025 MCKNLY LLC
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$REPO_ROOT"
VENV_BIN=".venv/bin"
PYTHON="$VENV_BIN/python"
UVICORN="$VENV_BIN/uvicorn"
if [[ ! -x "$PYTHON" ]]; then
echo "[launch-uvicorn-dev] Missing virtual environment (.venv). Create it with 'python -m venv .venv' and install dependencies before retrying." >&2
exit 1
fi
if [[ ! -x "$UVICORN" ]]; then
echo "[launch-uvicorn-dev] Uvicorn is not installed in .venv. Run '.venv/bin/pip install -e .[dev]' first." >&2
exit 1
fi
if [[ -f ".env" ]]; then
set -a
# shellcheck disable=SC1091
source ".env"
set +a
fi
readarray -t compose_exports < <("$PYTHON" - <<'PY'
import os
import re
from pathlib import Path
try:
import yaml # type: ignore
except Exception as exc: # pragma: no cover - best effort
raise SystemExit(f"[launch-uvicorn-dev] PyYAML is required: {exc}")
compose_path = Path("docker-compose.yml")
if not compose_path.exists():
raise SystemExit()
data = yaml.safe_load(compose_path.read_text(encoding="utf-8")) or {}
services = data.get("services") or {}
app = services.get("app") or {}
environment = app.get("environment") or {}
pattern = re.compile(r"\$\{([^}:]+)(?::-(.*?))?\}")
def resolve(value: str) -> str:
if value is None:
return ""
def repl(match: re.Match[str]) -> str:
var = match.group(1)
default = match.group(2) or ""
return os.environ.get(var, default)
return pattern.sub(repl, value)
for key, raw in environment.items():
if key in os.environ:
continue
resolved = resolve("" if raw is None else str(raw))
print(f"{key}={resolved}")
PY
)
for entry in "${compose_exports[@]}"; do
[[ -z "$entry" ]] && continue
IFS="=" read -r key value <<<"$entry"
export "$key=$value"
done
export LIVE_DASHBOARD_ENABLED="${LIVE_DASHBOARD_ENABLED:-true}"
APP_HOST="${APP_HOST:-127.0.0.1}"
APP_PORT="${APP_PORT:-8080}"
cleanup() {
if [[ -n "${UVICORN_PID:-}" ]]; then
pkill -TERM -P "$UVICORN_PID" 2>/dev/null || true
kill "$UVICORN_PID" 2>/dev/null || true
wait "$UVICORN_PID" 2>/dev/null || true
UVICORN_PID=""
fi
}
terminate() {
cleanup
exit 130
}
termterminate() {
cleanup
exit 143
}
trap cleanup EXIT
trap terminate INT
trap termterminate TERM
set +e
"$UVICORN" app.main:app --host "$APP_HOST" --port "$APP_PORT" --reload "$@" &
UVICORN_PID=$!
wait "$UVICORN_PID"
status=$?
set -e
UVICORN_PID=""
exit $status