Files
stackpilot/backend/main.py
T
menzeljandClaude Opus 4.8 7775128c07 Fix CORS_ORIGINS env parsing crash (pydantic-settings NoDecode), bump 0.1.1
list[str] settings fed from env were JSON-decoded by pydantic-settings
before the field validator ran, so a plain string like
CORS_ORIGINS=http://host:5009 raised JSONDecodeError on startup.
Annotate list env fields with NoDecode and parse CSV/JSON in the validator.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 16:20:36 +00:00

63 lines
1.6 KiB
Python

"""StackPilot backend — FastAPI application entry point."""
from __future__ import annotations
import logging
from contextlib import asynccontextmanager
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from sqlmodel import Session
from config import settings
from database import engine, init_db
from docker_client import DockerError
from routers import audit, auth, stacks, system, ws
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("stackpilot")
@asynccontextmanager
async def lifespan(app: FastAPI):
init_db()
# Register stacks that already exist on disk.
try:
with Session(engine) as session:
stacks.sync_discovered_stacks(session)
except Exception as exc: # noqa: BLE001
logger.warning("Stack discovery failed: %s", exc)
logger.info("StackPilot backend ready on port %s", settings.PORT)
yield
app = FastAPI(title="StackPilot", version="0.1.1", lifespan=lifespan)
app.add_middleware(
CORSMiddleware,
allow_origins=settings.CORS_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.exception_handler(DockerError)
async def docker_error_handler(_request: Request, exc: DockerError):
return JSONResponse(
status_code=502,
content={"error": exc.error, "detail": exc.detail},
)
app.include_router(auth.router)
app.include_router(stacks.router)
app.include_router(system.router)
app.include_router(audit.router)
app.include_router(ws.router)
@app.get("/api/health")
def health() -> dict:
return {"status": "ok"}