Ctrl K
ComunidadGuías…

launch-uvicorn-dev

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/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