Skip to content

Commit

Permalink
fix: Update Alembic migration workflow to use Python API and add prop…
Browse files Browse the repository at this point in the history
…er configuration

- Replace python -m alembic with direct API calls
- Add proper env.py and script.py.mako templates
- Improve error handling and logging
- Add automatic migration initialization
  • Loading branch information
devin-ai-integration[bot] committed Nov 10, 2024
1 parent 837ec1a commit f9bfee6
Showing 1 changed file with 110 additions and 137 deletions.
247 changes: 110 additions & 137 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,146 +59,119 @@ jobs:
export PYTHONPATH="${PYTHONPATH}:${PWD}"
echo "Current PYTHONPATH: $PYTHONPATH"
# Initialize Alembic if not already initialized
echo "Initializing Alembic..."
# Create alembic directory structure
mkdir -p alembic/versions
# Create alembic.ini with proper database URL
cat > alembic.ini << EOL
[alembic]
script_location = alembic
sqlalchemy.url = $DATABASE_URL
file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s

[loggers]
keys = root,sqlalchemy,alembic

[handlers]
keys = console

[formatters]
keys = generic

[logger_root]
level = WARN
handlers = console
qualname =

[logger_sqlalchemy]
level = WARN
handlers =
qualname = sqlalchemy.engine

[logger_alembic]
level = INFO
handlers =
qualname = alembic

[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic

[formatter_generic]
format = %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S
EOL

# Create env.py if it doesn't exist
if [ ! -f "alembic/env.py" ]; then
cat > alembic/env.py << 'EOL'
from logging.config import fileConfig
from sqlalchemy import engine_from_config
from sqlalchemy import pool
from alembic import context
import os

config = context.config

if config.config_file_name is not None:
fileConfig(config.config_file_name)

def run_migrations_offline() -> None:
url = os.getenv("DATABASE_URL")
context.configure(
url=url,
target_metadata=None,
literal_binds=True,
dialect_opts={"paramstyle": "named"},
)
with context.begin_transaction():
context.run_migrations()

def run_migrations_online() -> None:
configuration = config.get_section(config.config_ini_section)
configuration["sqlalchemy.url"] = os.getenv("DATABASE_URL")
connectable = engine_from_config(
configuration,
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)
with connectable.connect() as connection:
context.configure(
connection=connection,
target_metadata=None
)
with context.begin_transaction():
context.run_migrations()

if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()
EOL
fi
# Create Alembic directory structure
mkdir -p migrations/versions
# Create env.py
mkdir -p migrations
cat > migrations/env.py << 'EOL'
from logging.config import fileConfig
from sqlalchemy import engine_from_config
from sqlalchemy import pool
from alembic import context
import os
config = context.config
if config.config_file_name is not None:
fileConfig(config.config_file_name)
def run_migrations_offline() -> None:
url = os.getenv("DATABASE_URL")
context.configure(
url=url,
target_metadata=None,
literal_binds=True,
dialect_opts={"paramstyle": "named"},
)
with context.begin_transaction():
context.run_migrations()
def run_migrations_online() -> None:
configuration = config.get_section(config.config_ini_section)
if configuration is None:
configuration = {}
configuration["sqlalchemy.url"] = os.getenv("DATABASE_URL")
connectable = engine_from_config(
configuration,
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)
with connectable.connect() as connection:
context.configure(
connection=connection,
target_metadata=None
)
with context.begin_transaction():
context.run_migrations()
if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()
EOL
# Create script.py.mako
cat > migrations/script.py.mako << 'EOL'
"""${message}
Revision ID: ${up_revision}
Revises: ${down_revision | comma,n}
Create Date: ${create_date}
"""
from alembic import op
import sqlalchemy as sa
${imports if imports else ""}
# revision identifiers, used by Alembic.
revision = ${repr(up_revision)}
down_revision = ${repr(down_revision)}
branch_labels = ${repr(branch_labels)}
depends_on = ${repr(depends_on)}
def upgrade() -> None:
${upgrades if upgrades else "pass"}
def downgrade() -> None:
${downgrades if downgrades else "pass"}
EOL
# Create and run migration script
echo "Creating migration script..."
cat > run_migrations.py << 'EOL'
import os
import sys
import logging
from alembic import command
from alembic.config import Config

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('alembic')

def run_migrations():
try:
logger.info("Starting database migration")
logger.info(f"Current directory: {os.getcwd()}")
logger.info(f"Directory contents: {os.listdir('.')}")

# Load config from file
config = Config("alembic.ini")

# Set database URL
config.set_main_option("sqlalchemy.url", os.environ["DATABASE_URL"])

# Create initial migration if none exists
versions_dir = os.path.join('alembic', 'versions')
if not os.listdir(versions_dir):
logger.info("Creating initial migration...")
command.revision(config, message="Initial migration", autogenerate=True)

# Run the migration
command.upgrade(config, "head")

logger.info("Database migration completed successfully")
except Exception as e:
logger.error(f"Migration failed: {str(e)}", exc_info=True)
sys.exit(1)

if __name__ == "__main__":
run_migrations()
EOL

echo "Running migrations with Python script..."
import os
import sys
import logging
from alembic.config import Config
from alembic import command
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
try:
# Create alembic config
config = Config()
config.set_main_option('script_location', 'migrations')
config.set_main_option('sqlalchemy.url', os.environ['DATABASE_URL'])
# Initialize migrations if needed
if not os.path.exists('migrations/versions'):
os.makedirs('migrations/versions')
logger.info("Creating initial migration...")
command.revision(config, message="Initial migration", autogenerate=True)
# Run the migration
logger.info("Running database migrations...")
command.upgrade(config, "head")
logger.info("Migrations completed successfully")
except Exception as e:
logger.error(f"Migration failed: {str(e)}", exc_info=True)
sys.exit(1)
EOL
# Run the migration script
python run_migrations.py
- name: Run tests with coverage
working-directory: ./backend
Expand Down

0 comments on commit f9bfee6

Please sign in to comment.