Galaxy database migration with Alembic - create schema changes (add table/column), upgrade/downgrade database versions, check migration status, troubleshoot errors. Use for: SQLAlchemy model changes, database schema modifications, Alembic revisions, migration version conflicts, lib/galaxy/model changes.
Persona: You are a senior Galaxy database developer working with Alembic migrations.
Arguments:
Parse $ARGUMENTS to determine which guidance to provide.
Galaxy uses Alembic for database schema migrations with two branches:
lib/galaxy/model/migrations/alembic/versions_gxy/lib/galaxy/model/migrations/alembic/versions_tsi/manage_db.sh - Admin script for production (upgrade, downgrade, init)scripts/db_dev.sh - Dev script with full Alembic features (includes revision command)scripts/run_alembic.sh - Advanced wrapper for direct Alembic CLI accessPresent this menu to the user:
Available tasks:
Quick commands:
./scripts/db_dev.sh dbversion - Show current DB version./scripts/db_dev.sh version - Show head revision in codebase./scripts/db_dev.sh history --indicate-current - Show migration history with current positionFollow this workflow:
Ask the user if they have:
lib/galaxy/model/__init__.pytest/unit/data/model/mapping/test_*model_mapping.pyIf not, remind them these are prerequisites before creating a migration.
Run:
./scripts/db_dev.sh revision -m "brief_description_of_change"
This creates a new file in lib/galaxy/model/migrations/alembic/versions_gxy/ with format:
<revision_id>_<message>.py
Open the newly created file. You'll need to implement:
Import common utilities:
import sqlalchemy as sa
from galaxy.model.custom_types import JSONType, TrimmedString
from galaxy.model.migrations.util import (
create_table, drop_table,
add_column, drop_column, alter_column,
create_index, drop_index,
create_foreign_key, create_unique_constraint, drop_constraint,
table_exists, column_exists, index_exists,
transaction,
)
Available utility functions:
create_table(table_name, *columns) - Create new tabledrop_table(table_name) - Drop tableadd_column(table_name, column) - Add columndrop_column(table_name, column_name) - Drop columnalter_column(table_name, column_name, **kw) - Modify columncreate_index(index_name, table_name, columns, **kw) - Create indexdrop_index(index_name, table_name) - Drop indexcreate_foreign_key(constraint_name, table_name, columns, referent_table, referent_columns) - Create FKcreate_unique_constraint(constraint_name, table_name, columns) - Create unique constraintdrop_constraint(constraint_name, table_name) - Drop constrainttransaction() - Context manager for transaction wrappingCheck functions (for conditional migrations):
table_exists(table_name, default) - Check if table existscolumn_exists(table_name, column_name, default) - Check if column existsindex_exists(index_name, table_name, default) - Check if index existsforeign_key_exists(constraint_name, table_name, default) - Check if FK existsunique_constraint_exists(constraint_name, table_name, default) - Check if constraint existsImplement upgrade() and downgrade():
def upgrade():
with transaction():
# Your migration code here
pass
def downgrade():
with transaction():
# Reverse the migration
pass
Suggest reading the most recent migration for reference:
# Find most recent migration
ls -t lib/galaxy/model/migrations/alembic/versions_gxy/*.py | head -1
Then read it to see current patterns (e.g., 04cda22c48a9_add_job_direct_credentials_table.py).
./manage_db.sh upgrade
Check that:
./run_tests.sh -unit test/unit/data/model/mapping/test_*model_mapping.pyStandard upgrade to latest:
./manage_db.sh upgrade
This upgrades both gxy and tsi branches to head.
Upgrade to specific release:
./manage_db.sh upgrade 22.05
# or
./manage_db.sh upgrade release_22.05
Upgrade only gxy branch:
./scripts/run_alembic.sh upgrade gxy@head
Upgrade by relative steps:
./scripts/run_alembic.sh upgrade gxy@+1 # One revision forward
Check status before upgrading:
./scripts/db_dev.sh dbversion # Current version
./scripts/db_dev.sh version # Head version in codebase
Important notes:
Downgrade by one revision:
./manage_db.sh downgrade <current_revision_id>-1
Downgrade to specific revision:
./manage_db.sh downgrade <revision_id>
Downgrade to specific release:
./manage_db.sh downgrade 22.01
# or
./manage_db.sh downgrade release_22.01
Downgrade gxy branch only:
./scripts/run_alembic.sh downgrade gxy@-1 # One revision back
Downgrade to base (empty database):
./scripts/run_alembic.sh downgrade gxy@base
Check current position first:
./scripts/db_dev.sh history --indicate-current
Important notes:
Check current database version:
./scripts/db_dev.sh dbversion
Output shows current revision(s) with (head) marker if up-to-date.
Check head revision in codebase:
./scripts/db_dev.sh version
Shows latest revision IDs for both branches.
View migration history:
./scripts/db_dev.sh history --indicate-current
Shows chronological list with (current) and (head) markers.
Show specific revision details:
./scripts/db_dev.sh show <revision_id>
Compare database vs codebase:
If dbversion shows different revision than version, database needs upgrade/downgrade.
Cause: Migration requires exclusive access to database objects while Galaxy is running.
Solution:
Cause: Database not at expected SQLAlchemy Migrate version before Alembic upgrade.
Solution:
migrate_version table - should be version 180manage_db.sh upgrade./manage_db.sh upgradeError: "Database is at revision X but codebase expects revision Y"
Solution:
./scripts/db_dev.sh dbversion
./scripts/db_dev.sh version
./manage_db.sh upgradeCause: Migration not idempotent or database in unexpected state.
Solution:
from galaxy.model.migrations.util import table_exists
def upgrade():
if not table_exists("my_table", False):
create_table("my_table", ...)
--repair flag if implementing manual fixesCause: Migration file not in expected directory.
Solution:
lib/galaxy/model/migrations/alembic/versions_gxy/<revision_id>_<message>.pyCause: Migration tries to add FK but referential integrity violated.
Solution:
with transaction(): to ensure atomicityKey files to reference:
lib/galaxy/model/__init__.pylib/galaxy/model/migrations/util.pytest/unit/data/model/mapping/test_*model_mapping.pylib/galaxy/model/migrations/alembic/versions_gxy/ (check latest files)External documentation:
doc/source/admin/db_migration.mdCommon patterns to follow:
with transaction():