mirror of
https://github.com/wahyd4/you-music.git
synced 2026-08-08 20:59:47 +10:00
6.3 KiB
6.3 KiB
Database Migrations Guide
YouMusic uses Alembic for database schema migrations. This ensures safe schema changes without data loss.
Quick Start
View Migration Status
cd backend
./migrate.sh current
Create a New Migration
When you modify database models in app/models/models.py:
cd backend
./migrate.sh create "Add new field description"
Apply Migrations
cd backend
./migrate.sh upgrade
Rollback a Migration
cd backend
./migrate.sh downgrade # Go back one migration
# or
./migrate.sh downgrade <revision_id> # Go to specific version
Migration Commands
| Command | Description |
|---|---|
./migrate.sh create "message" |
Create new migration with autogenerate |
./migrate.sh upgrade |
Apply all pending migrations |
./migrate.sh downgrade |
Rollback last migration |
./migrate.sh history |
View migration history |
./migrate.sh current |
Show current database version |
./migrate.sh stamp head |
Mark database as current without running migrations |
How It Works
- Models - Define your schema in
app/models/models.py - Generate Migration - Alembic compares models to current DB and creates migration script
- Review Migration - Check
alembic/versions/*.pyfile before applying - Apply Migration - Run upgrade to apply changes to database
Migration Workflow
Adding a New Field
- Add field to model:
# app/models/models.py
class Music(Base):
# ... existing fields ...
new_field: Mapped[Optional[str]] = mapped_column(String, nullable=True)
- Create migration:
./migrate.sh create "Add new_field to music table"
-
Review generated migration in
alembic/versions/ -
Apply migration:
./migrate.sh upgrade
Renaming a Field
Alembic may detect this as drop + add. Manually edit the migration:
# Before (auto-generated)
def upgrade():
batch_op.drop_column('old_name')
batch_op.add_column(sa.Column('new_name', sa.String(), nullable=True))
# After (manual edit)
def upgrade():
batch_op.alter_column('old_name', new_column_name='new_name')
Deleting a Field
- Remove from model
- Generate migration:
./migrate.sh create "Remove old_field" - Review - ensure data you want is preserved
- Apply:
./migrate.sh upgrade
Production Deployment
First Deployment (New Instance)
# Migrations will run automatically on startup
# Or manually:
./migrate.sh upgrade
Updating Existing Instance
# 1. Backup database
cp data/youmusic.db data/youmusic.db.backup
# 2. Pull latest code
git pull
# 3. Install dependencies
uv sync
# 4. Apply migrations
./migrate.sh upgrade
# 5. Restart application
Docker Deployment
Migrations run automatically when the container starts (via startup script).
To run manually in container:
docker exec -it youmusic /app/backend/migrate.sh current
docker exec -it youmusic /app/backend/migrate.sh upgrade
Kubernetes Deployment
Migrations run as an init container before the main application starts.
Check migration status:
kubectl logs -f deployment/youmusic -c migrations
Troubleshooting
"Target database is not up to date"
Your database is behind. Run:
./migrate.sh upgrade
"Can't locate revision identified by 'xyz'"
Migration files are missing or database is inconsistent. Check:
./migrate.sh history
./migrate.sh current
Rollback Failed Migration
# Downgrade to previous version
./migrate.sh downgrade
# Or to specific version
./migrate.sh downgrade <revision_id>
Reset Database (Dev Only - DATA LOSS!)
# Delete database
rm data/youmusic.db
# Recreate with latest schema
./migrate.sh upgrade
Manually Fix Database Version
If migrations got out of sync:
# Stamp to specific version (doesn't run migrations)
./migrate.sh stamp <revision_id>
# Or to latest
./migrate.sh stamp head
Files and Directories
backend/
├── alembic/ # Migration configuration
│ ├── versions/ # Migration scripts
│ │ └── *.py # Individual migrations
│ ├── env.py # Alembic environment config
│ └── script.py.mako # Migration template
├── alembic.ini # Alembic settings
├── migrate.sh # Helper script
└── app/
└── models/
└── models.py # SQLAlchemy models (source of truth)
Best Practices
- Always Review - Check auto-generated migrations before applying
- Test First - Run migrations on dev/staging before production
- Backup Data - Always backup database before migrations in production
- One Change Per Migration - Keep migrations focused and atomic
- Descriptive Messages - Use clear migration messages
- Version Control - Commit migration files to git
- Never Edit Applied Migrations - Create new ones instead
- Document Complex Changes - Add comments in migration files
Advanced Usage
Manual Migration (No Autogenerate)
source .venv/bin/activate
alembic revision -m "Manual migration"
# Edit the created file manually
Offline SQL Generation
source .venv/bin/activate
alembic upgrade head --sql > migration.sql
# Review migration.sql before applying
Branching and Merging
# Create branch-specific migration
alembic revision -m "Feature branch change" --branch-label feature
# Merge branches
alembic merge -m "Merge branches" head1 head2
SQLite Specific Notes
- Uses
batch_alter_tablefor schema changes (required for SQLite) - Some operations may require table recreation
- Foreign key constraints temporarily disabled during migrations
render_as_batch=Truein env.py handles this automatically
Migration History Example
$ ./migrate.sh history
01209c730b33 -> (head), Initial migration
<base> -> 01209c730b33, Initial migration
Getting Help
- Alembic Docs: https://alembic.sqlalchemy.org/
- SQLAlchemy Docs: https://docs.sqlalchemy.org/
- Project Issues: Check GitHub issues
See Also
AGENTS.md- AI/LLM context about the projectDEV_QUICK_START.md- Development setup guideDEPLOYMENT.md- Deployment instructions