"""Run Loyalty migrations safely. Phase 7.0's 0001_initial uses Base.metadata.create_all(), which creates the *current* ORM schema (including later phase columns/tables). Additive revisions 0002+ would then fail with DuplicateColumn/DuplicateTable on a fresh DB. After 0001, stamp head so the DB matches the model tree. Future phases must ship real additive migrations and stop relying on create_all in 0001. """ from __future__ import annotations from alembic import command from alembic.config import Config from alembic.script import ScriptDirectory from alembic.runtime.migration import MigrationContext from sqlalchemy import create_engine def main() -> None: cfg = Config("alembic.ini") command.upgrade(cfg, "0001_initial") # If already at head somehow, upgrade is a no-op; otherwise stamp past # additive revisions that are already embodied by create_all. sync_url = None try: from app.core.config import settings sync_url = settings.database_url_sync except Exception: pass head = ScriptDirectory.from_config(cfg).get_current_head() if sync_url: engine = create_engine(sync_url) with engine.connect() as conn: ctx = MigrationContext.configure(conn) current = ctx.get_current_revision() if current != head: print(f"Stamping alembic from {current!r} -> {head!r} after create_all") command.stamp(cfg, "head") else: print(f"Already at head {head}") else: command.stamp(cfg, "head") print(f"Stamped head {head}") if __name__ == "__main__": main()