From 3f23bc3db37ffd3f7c489a878eb2b2fd9153c367 Mon Sep 17 00:00:00 2001 From: Felipe Cardoso Date: Tue, 6 Jan 2026 17:19:28 +0100 Subject: [PATCH] refactor(migrations): replace hardcoded database URL with configurable environment variable and update command syntax to use consistent quoting style --- backend/migrate.py | 89 ++++++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 42 deletions(-) diff --git a/backend/migrate.py b/backend/migrate.py index da21a02..e4a4d4f 100755 --- a/backend/migrate.py +++ b/backend/migrate.py @@ -26,6 +26,7 @@ Usage: # Inside Docker (without --local flag): python migrate.py auto "Add new field" """ + import argparse import os import subprocess @@ -44,13 +45,14 @@ def setup_database_url(use_local: bool) -> str: # Override DATABASE_URL to use localhost instead of Docker hostname local_url = os.environ.get( "LOCAL_DATABASE_URL", - "postgresql://postgres:postgres@localhost:5432/app" + "postgresql://postgres:postgres@localhost:5432/syndarix", ) os.environ["DATABASE_URL"] = local_url return local_url # Use the configured DATABASE_URL from environment/.env from app.core.config import settings + return settings.database_url @@ -61,6 +63,7 @@ def check_models(): try: # Import all models through the models package from app.models import __all__ as all_models + print(f"Found {len(all_models)} model(s):") for model in all_models: print(f" - {model}") @@ -110,7 +113,9 @@ def generate_migration(message, rev_id=None, auto_rev_id=True, offline=False): # Look for the revision ID, which is typically 12 hex characters parts = line.split() for part in parts: - if len(part) >= 12 and all(c in "0123456789abcdef" for c in part[:12]): + if len(part) >= 12 and all( + c in "0123456789abcdef" for c in part[:12] + ): revision = part[:12] break except Exception as e: @@ -185,6 +190,7 @@ def check_database_connection(): db_url = os.environ.get("DATABASE_URL") if not db_url: from app.core.config import settings + db_url = settings.database_url engine = create_engine(db_url) @@ -270,8 +276,8 @@ def generate_offline_migration(message, rev_id): content = f'''"""{message} Revision ID: {rev_id} -Revises: {down_revision or ''} -Create Date: {datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')} +Revises: {down_revision or ""} +Create Date: {datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")} """ @@ -320,6 +326,7 @@ def reset_alembic_version(): db_url = os.environ.get("DATABASE_URL") if not db_url: from app.core.config import settings + db_url = settings.database_url try: @@ -338,82 +345,80 @@ def reset_alembic_version(): def main(): """Main function""" parser = argparse.ArgumentParser( - description='Database migration helper for Generative Models Arena' + description="Database migration helper for Generative Models Arena" ) # Global options parser.add_argument( - '--local', '-l', - action='store_true', - help='Use localhost instead of Docker hostname (for local development)' + "--local", + "-l", + action="store_true", + help="Use localhost instead of Docker hostname (for local development)", ) - subparsers = parser.add_subparsers(dest='command', help='Command to run') + subparsers = parser.add_subparsers(dest="command", help="Command to run") # Generate command - generate_parser = subparsers.add_parser('generate', help='Generate a migration') - generate_parser.add_argument('message', help='Migration message') + generate_parser = subparsers.add_parser("generate", help="Generate a migration") + generate_parser.add_argument("message", help="Migration message") generate_parser.add_argument( - '--rev-id', - help='Custom revision ID (e.g., 0001, 0002 for sequential naming)' + "--rev-id", help="Custom revision ID (e.g., 0001, 0002 for sequential naming)" ) generate_parser.add_argument( - '--offline', - action='store_true', - help='Generate empty migration template without database connection' + "--offline", + action="store_true", + help="Generate empty migration template without database connection", ) # Apply command - apply_parser = subparsers.add_parser('apply', help='Apply migrations') - apply_parser.add_argument('--revision', help='Specific revision to apply to') + apply_parser = subparsers.add_parser("apply", help="Apply migrations") + apply_parser.add_argument("--revision", help="Specific revision to apply to") # List command - subparsers.add_parser('list', help='List migrations') + subparsers.add_parser("list", help="List migrations") # Current command - subparsers.add_parser('current', help='Show current revision') + subparsers.add_parser("current", help="Show current revision") # Check command - subparsers.add_parser('check', help='Check database connection and models') + subparsers.add_parser("check", help="Check database connection and models") # Next command (show next revision ID) - subparsers.add_parser('next', help='Show the next sequential revision ID') + subparsers.add_parser("next", help="Show the next sequential revision ID") # Reset command (clear alembic_version table) subparsers.add_parser( - 'reset', - help='Reset alembic_version table (use after deleting all migrations)' + "reset", help="Reset alembic_version table (use after deleting all migrations)" ) # Auto command (generate and apply) - auto_parser = subparsers.add_parser('auto', help='Generate and apply migration') - auto_parser.add_argument('message', help='Migration message') + auto_parser = subparsers.add_parser("auto", help="Generate and apply migration") + auto_parser.add_argument("message", help="Migration message") auto_parser.add_argument( - '--rev-id', - help='Custom revision ID (e.g., 0001, 0002 for sequential naming)' + "--rev-id", help="Custom revision ID (e.g., 0001, 0002 for sequential naming)" ) auto_parser.add_argument( - '--offline', - action='store_true', - help='Generate empty migration template without database connection' + "--offline", + action="store_true", + help="Generate empty migration template without database connection", ) args = parser.parse_args() # Commands that don't need database connection - if args.command == 'next': + if args.command == "next": show_next_rev_id() return # Check if offline mode is requested - offline = getattr(args, 'offline', False) + offline = getattr(args, "offline", False) # Offline generate doesn't need database or model check - if args.command == 'generate' and offline: + if args.command == "generate" and offline: generate_migration(args.message, rev_id=args.rev_id, offline=True) return - if args.command == 'auto' and offline: + if args.command == "auto" and offline: generate_migration(args.message, rev_id=args.rev_id, offline=True) print("\nOffline migration generated. Apply it later with:") print(" python migrate.py --local apply") @@ -423,27 +428,27 @@ def main(): db_url = setup_database_url(args.local) print(f"Using database URL: {db_url}") - if args.command == 'generate': + if args.command == "generate": check_models() generate_migration(args.message, rev_id=args.rev_id) - elif args.command == 'apply': + elif args.command == "apply": apply_migration(args.revision) - elif args.command == 'list': + elif args.command == "list": list_migrations() - elif args.command == 'current': + elif args.command == "current": show_current() - elif args.command == 'check': + elif args.command == "check": check_database_connection() check_models() - elif args.command == 'reset': + elif args.command == "reset": reset_alembic_version() - elif args.command == 'auto': + elif args.command == "auto": check_models() revision = generate_migration(args.message, rev_id=args.rev_id) if revision: