#!/usr/bin/env python3 """Apply SQL migrations in order against TRF_DATABASE_URL (WP-0011). Idempotent migrations (IF NOT EXISTS / OR REPLACE). Safe to re-run. Uses the admin/bootstrap DSN — typically the CNPG owner role, not trf_app. """ from __future__ import annotations import os import sys from pathlib import Path import psycopg MIGRATIONS_DIR = Path(os.environ.get("TRF_MIGRATIONS_DIR", "/src/migrations")) def main() -> None: dsn = os.environ.get("TRF_DATABASE_URL") or os.environ.get("TRF_MIGRATE_DATABASE_URL") if not dsn: print("TRF_DATABASE_URL or TRF_MIGRATE_DATABASE_URL is required", file=sys.stderr) sys.exit(1) files = sorted(MIGRATIONS_DIR.glob("*.sql")) if not files: print(f"no migrations in {MIGRATIONS_DIR}", file=sys.stderr) sys.exit(1) with psycopg.connect(dsn) as conn: for path in files: print(f"applying {path.name} ...") conn.execute(path.read_text(encoding="utf-8")) conn.commit() print(f" ok {path.name}") print(f"applied {len(files)} migration(s)") if __name__ == "__main__": main()