All checks were successful
Deploy to Production / deploy (push) Successful in 1m45s
- Added new migrate.ts module to handle automatic database migrations using drizzle-orm - Modified server startup to run migrations before Express initialization - Added comprehensive documentation in AUTO_MIGRATION_SUMMARY.md explaining the implementation - Updated DATABASE_SETUP.md to reflect automatic migration process and troubleshooting steps - Added error handling to exit process if migrations fail during startup - Implemented clear
267 lines
5.7 KiB
Markdown
267 lines
5.7 KiB
Markdown
# Automatic Database Migrations - Implementation Summary
|
|
|
|
## What Was Implemented
|
|
|
|
Database migrations now run **automatically** every time the API server starts. This eliminates the need to manually run migration commands.
|
|
|
|
## Changes Made
|
|
|
|
### 1. Created Migration Runner (`apps/api/src/db/migrate.ts`)
|
|
|
|
A new module that:
|
|
- Connects to MySQL using environment variables
|
|
- Runs pending migrations from the `drizzle/` folder
|
|
- Provides clear console output with emojis
|
|
- Handles errors gracefully
|
|
|
|
```typescript
|
|
export async function runMigrations() {
|
|
console.log('🔄 Running database migrations...');
|
|
// ... migration logic ...
|
|
console.log('✅ Database migrations completed successfully');
|
|
}
|
|
```
|
|
|
|
### 2. Integrated into Server Startup (`apps/api/src/index.ts`)
|
|
|
|
Modified the server startup to:
|
|
- Run migrations before starting Express
|
|
- Exit with error if migrations fail
|
|
- Provide clear startup sequence
|
|
|
|
```typescript
|
|
async function startServer() {
|
|
await runMigrations(); // ← Runs automatically
|
|
app.listen(PORT, () => {
|
|
console.log(`API server running on port ${PORT}`);
|
|
});
|
|
}
|
|
```
|
|
|
|
## Benefits
|
|
|
|
### ✅ **No Manual Steps**
|
|
- Just run `docker-compose up -d --build`
|
|
- Migrations run automatically
|
|
- Database is always up-to-date
|
|
|
|
### ✅ **Idempotent**
|
|
- Safe to run multiple times
|
|
- Only applies new migrations
|
|
- No duplicate data or errors
|
|
|
|
### ✅ **Developer Friendly**
|
|
- Clear console output
|
|
- Easy to debug
|
|
- Works in development and production
|
|
|
|
### ✅ **CI/CD Ready**
|
|
- No extra deployment steps
|
|
- Migrations run on container start
|
|
- Automatic rollout of schema changes
|
|
|
|
## How It Works
|
|
|
|
### Startup Sequence
|
|
|
|
```
|
|
1. Docker starts API container
|
|
2. Node.js starts
|
|
3. Environment variables loaded (.env)
|
|
4. 🔄 Migrations run automatically
|
|
5. ✅ Migrations complete
|
|
6. Express server starts
|
|
7. API ready to accept requests
|
|
```
|
|
|
|
### Console Output
|
|
|
|
When you start the API, you'll see:
|
|
|
|
```bash
|
|
[OpenAIClient] Initialized with timeout: 600s, maxRetries: 2
|
|
ENV ADMIN_PASSWORD loaded: true
|
|
🔄 Running database migrations...
|
|
✅ Database migrations completed successfully
|
|
API server running on port 3301
|
|
```
|
|
|
|
## Testing
|
|
|
|
### Verify Automatic Migrations
|
|
|
|
```bash
|
|
# 1. Reset database (deletes all data!)
|
|
docker-compose down -v
|
|
|
|
# 2. Start fresh
|
|
docker-compose up -d --build
|
|
|
|
# 3. Watch the logs
|
|
docker-compose logs -f api
|
|
|
|
# You should see:
|
|
# 🔄 Running database migrations...
|
|
# ✅ Database migrations completed successfully
|
|
```
|
|
|
|
### Verify Tables Created
|
|
|
|
```bash
|
|
docker exec voxblog-mysql mysql -u voxblog -pvoxblogAppPass123! voxblog -e "SHOW TABLES;"
|
|
```
|
|
|
|
Expected output:
|
|
```
|
|
Tables_in_voxblog
|
|
__drizzle_migrations
|
|
audio_clips
|
|
posts
|
|
settings
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Migrations Don't Run
|
|
|
|
**Check API logs:**
|
|
```bash
|
|
docker-compose logs api | grep -i migration
|
|
```
|
|
|
|
**Common issues:**
|
|
- MySQL not ready yet (wait 30 seconds)
|
|
- Wrong database credentials in `.env`
|
|
- Migration files missing in `apps/api/drizzle/`
|
|
|
|
### Migration Fails
|
|
|
|
**Error in logs:**
|
|
```bash
|
|
❌ Migration failed: [error details]
|
|
```
|
|
|
|
**Solutions:**
|
|
1. Check MySQL is healthy: `docker-compose ps mysql`
|
|
2. Verify credentials in `.env`
|
|
3. Check migration files exist: `ls apps/api/drizzle/`
|
|
4. Run manually: `docker exec voxblog-api sh -c "cd /app/apps/api && pnpm drizzle:migrate"`
|
|
|
|
### Server Won't Start
|
|
|
|
If migrations fail, the server exits with error code 1.
|
|
|
|
**Check logs:**
|
|
```bash
|
|
docker-compose logs api
|
|
```
|
|
|
|
**Restart after fixing:**
|
|
```bash
|
|
docker-compose restart api
|
|
```
|
|
|
|
## Manual Migration (Still Available)
|
|
|
|
You can still run migrations manually if needed:
|
|
|
|
```bash
|
|
# Inside container
|
|
docker exec voxblog-api sh -c "cd /app/apps/api && pnpm drizzle:migrate"
|
|
|
|
# Or using pnpm scripts
|
|
docker exec voxblog-api pnpm --filter api drizzle:migrate
|
|
```
|
|
|
|
## Creating New Migrations
|
|
|
|
When you modify the schema (`apps/api/src/db/schema.ts`):
|
|
|
|
```bash
|
|
# 1. Generate migration file
|
|
docker exec voxblog-api sh -c "cd /app/apps/api && pnpm drizzle:generate"
|
|
|
|
# 2. Restart API (migrations run automatically)
|
|
docker-compose restart api
|
|
|
|
# 3. Verify migration applied
|
|
docker-compose logs api | grep migration
|
|
```
|
|
|
|
## Production Deployment
|
|
|
|
### Zero-Downtime Deployment
|
|
|
|
1. **Build new image** with schema changes
|
|
2. **Deploy new container** - migrations run automatically
|
|
3. **Old container** continues serving requests
|
|
4. **New container** takes over after migrations complete
|
|
|
|
### Rollback Strategy
|
|
|
|
If a migration fails:
|
|
1. Container exits with error
|
|
2. Old container keeps running
|
|
3. Fix migration and redeploy
|
|
4. Or rollback to previous version
|
|
|
|
## Best Practices
|
|
|
|
### ✅ **DO**
|
|
- Test migrations locally first
|
|
- Make migrations backward compatible
|
|
- Keep migrations small and focused
|
|
- Add indexes in separate migrations
|
|
- Document breaking changes
|
|
|
|
### ❌ **DON'T**
|
|
- Don't delete migration files
|
|
- Don't modify existing migrations
|
|
- Don't make breaking schema changes without planning
|
|
- Don't skip testing migrations
|
|
|
|
## Files Modified
|
|
|
|
1. **`apps/api/src/db/migrate.ts`** (new)
|
|
- Migration runner logic
|
|
- Error handling
|
|
- Console output
|
|
|
|
2. **`apps/api/src/index.ts`** (modified)
|
|
- Import migration runner
|
|
- Call migrations before server start
|
|
- Async startup function
|
|
|
|
3. **`DATABASE_SETUP.md`** (updated)
|
|
- Document automatic migrations
|
|
- Update troubleshooting guide
|
|
- Remove manual migration steps
|
|
|
|
## Migration History
|
|
|
|
Migrations are tracked in the `__drizzle_migrations` table:
|
|
|
|
```sql
|
|
SELECT * FROM __drizzle_migrations;
|
|
```
|
|
|
|
Shows:
|
|
- Migration ID
|
|
- Hash
|
|
- Created timestamp
|
|
|
|
## Future Enhancements
|
|
|
|
Potential improvements:
|
|
- Migration rollback command
|
|
- Migration status endpoint (`/api/migrations`)
|
|
- Dry-run mode
|
|
- Migration locking for multi-instance deployments
|
|
- Slack/email notifications on migration failures
|
|
|
|
---
|
|
|
|
**Status**: ✅ Implemented and Working
|
|
**Last Updated**: 2025-10-26
|
|
**Author**: Automated Migration System
|