From ef8285e583c9479f2c21b88cfd6795a02669789e Mon Sep 17 00:00:00 2001 From: Martin Hohenberg Date: Thu, 18 Jun 2026 21:21:51 +0200 Subject: [PATCH] Auto-stamp or migrate on startup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On boot, run_migrations() checks the Alembic revision: - no revision + tables exist → stamp head (db.sql was run manually) - no revision + no tables → upgrade head (fresh install) - revision present → upgrade head (no-op if already current) Co-Authored-By: Claude Sonnet 4.6 --- app/db.py | 23 ++++++++++++++++++++++- app/main.py | 3 ++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/app/db.py b/app/db.py index fb3d2da..e213b73 100644 --- a/app/db.py +++ b/app/db.py @@ -1,8 +1,14 @@ +import logging import os -from sqlalchemy import create_engine, text +from alembic import command +from alembic.config import Config +from alembic.runtime.migration import MigrationContext +from sqlalchemy import create_engine, inspect, text from sqlalchemy.orm import Session, sessionmaker +logger = logging.getLogger("pops") + def _db_url() -> str: return ( @@ -24,6 +30,21 @@ def get_db(): db.close() +def run_migrations() -> None: + alembic_cfg = Config("alembic.ini") + with engine.connect() as conn: + current_rev = MigrationContext.configure(conn).get_current_revision() + if current_rev is None: + if "printers" in inspect(engine).get_table_names(): + logger.info("Existing schema detected, stamping Alembic to head") + command.stamp(alembic_cfg, "head") + else: + logger.info("Fresh database, running migrations") + command.upgrade(alembic_cfg, "head") + else: + command.upgrade(alembic_cfg, "head") + + def check_db() -> tuple[bool, str]: try: with engine.connect() as conn: diff --git a/app/main.py b/app/main.py index f07b789..9fc1ce2 100644 --- a/app/main.py +++ b/app/main.py @@ -3,7 +3,7 @@ from contextlib import asynccontextmanager from fastapi import FastAPI -from app.db import check_db +from app.db import check_db, run_migrations from app.routers import filaments, pricing, print_jobs, printers, todos logger = logging.getLogger("pops") @@ -14,6 +14,7 @@ async def lifespan(app: FastAPI): ok, msg = check_db() if ok: logger.info("Database connection OK") + run_migrations() else: logger.warning("Database unreachable: %s", msg) yield