fix(alembic): merge migration heads and make enum upgrades idempotent
## Overview
This MR fixes local startup failures during `docker compose up -d` by resolving Alembic migration issues in the database initialization flow.
### What problem does it solve?
`db-init` runs `alembic upgrade head` during startup. That was failing for two reasons:
- Alembic had multiple heads after the `role_requests` migration was added, so `head` was ambiguous.
- On existing local Postgres volumes, enum migrations for `medicinetypeenum` could fail with duplicate label errors because values like `ointment` had already been added previously.
### What does this MR do and why?
This MR makes the migration chain safe and deterministic for local startup and rebuilds.
- It adds a merge migration so Alembic has a single head again.
- It makes the medicine enum migrations idempotent by using `ADD VALUE IF NOT EXISTS`.
### Motivation
The main motivation was to unblock local development and Docker-based setup. Without this fix, `db-init` exited with code `1`, which prevented the `api` service from starting.
### Approach Taken
- Added a no-op Alembic merge revision instead of rewriting existing migration history.
- Updated enum migrations to tolerate partially initialized local databases and repeated startup attempts.
### Trade-offs
Using `IF NOT EXISTS` is more resilient for local/dev environments, but it can hide some out-of-band schema drift for enum values. In this case, that trade-off is acceptable because the goal is reliable initialization without breaking existing local volumes.
## Changes Made
### Files added / modified / removed
- Added: `alembic/versions/c9d4e5f6a7b8_merge_role_requests_and_medicine_enum_heads.py`
- Modified: `alembic/versions/add_ointment_powder_to_medicine_type_enum.py`
- Modified: `alembic/versions/add_drops_to_medicine_type_enum.py`
### New models, services, or utilities introduced
- Added a new Alembic merge revision to unify migration history.
- No new application models, services, or utilities were introduced.
### API endpoint changes
- No API contract changes.
- No request/response schema changes.
### Configuration changes
- No application configuration changes.
- No new environment variables added.
## Technical Details
### Root Cause
- The migration graph had two heads:
- `8f6c2a4d1b30`
- `add_drops_to_medicine_type_enum`
- `db-init` executes `alembic upgrade head`, which fails when multiple heads exist.
- After resolving that, startup still failed on some existing databases because enum migrations attempted to add values that were already present.
### How the fix addresses it
- The merge migration creates a single Alembic head without changing existing schema behavior.
- The enum migrations now use `ALTER TYPE ... ADD VALUE IF NOT EXISTS`, which allows reruns against existing local databases without crashing.
### Architecture / Data Flow Notes
- No service-layer or endpoint architecture changes.
- No new database tables or columns were introduced by this MR.
- This is primarily a migration-history and startup reliability fix.
## Type of Change
- [x] 🐛 Bug fix (non-breaking change that fixes an issue)
- [ ] ✨ New feature (non-breaking change that adds functionality)
- [ ] 💥 Breaking change
- [ ] 📝 Documentation update
- [ ] ♻️ Refactor
- [ ] ⚡ Performance improvement
- [ ] 🧪 Test update
- [ ] 🔧 Configuration change
- [ ] 🚨 Security fix
- [ ] 🗑️ Deprecation
## Related Issues / References
- Closes #<issue-id-if-applicable>
## Screenshots or Screen Recordings
Backend/migration-only change. No UI screenshots.
Recommended attachments for review:
- `docker compose up -d --build` success output
- `docker compose ps -a`
- `docker compose logs db-init --tail 80`
## How to Validate Locally
### Previous behavior
- `docker compose up -d` failed because `db-init` exited with code `1`.
- Alembic reported multiple heads, or enum migrations failed with duplicate enum label errors.
### Steps to validate
1. Pull this branch.
2. Run `docker compose up -d --build`.
3. Run `docker compose ps -a`.
4. Confirm `db-init` exited with status `0`.
5. Confirm `api` is running on port `8000`.
6. Run `docker compose logs db-init --no-color --tail 80`.
7. Confirm logs show `Database migrations completed successfully!`
8. Optionally run `uv run alembic heads` and confirm only one head is present.
### New behavior
- `db-init` completes successfully.
- The migration graph resolves to a single head.
- Existing local DB volumes no longer fail on repeated enum-value additions.
- `api` starts normally after database initialization.
## Testing Done
### Manual verification performed
- Verified `uv run alembic heads` returns a single head.
- Verified `docker compose up -d --build` completes successfully.
- Verified `docker compose ps -a` shows:
- `db-init` exited with `0`
- `api` is `Up`
- Verified `docker compose logs db-init --no-color --tail 80` contains successful migration completion.
- Verified `docker compose logs api --no-color --tail 40` shows application startup completed.
### Automated tests
- No unit or API tests were added/updated in this MR.
- Full test suite was not run as part of this change.
### Test Commands Run
```bash
uv run alembic heads
docker compose up -d --build
docker compose ps -a
docker compose logs db-init --no-color --tail 80
docker compose logs api --no-color --tail 40
Code Quality Checklist
-
Change follows existing Alembic migration patterns -
No API behavior changes introduced -
No destructive migration history rewrite performed -
Ruff checks run -
Mypy checks run -
Bandit scan run -
Automated test suite run
Known Limitations / Technical Debt
-
IF NOT EXISTSimproves resilience but may mask enum drift if values are added manually outside migrations. - A non-blocking LogBull startup warning still exists because
LOGBULL_PROJECT_IDis not a UUID. This MR does not address that.
Additional Notes
- The fix intentionally preserves migration history by merging heads rather than editing old revisions in place.
- This change is low-risk for runtime behavior because it does not alter API logic or service flow.
- Main impact is improving startup reliability for Docker/local development.
MR Acceptance Checklist
-
Code works as intended and solves the stated problem -
Existing functionality remains intact -
Migration chain is now valid and deterministic -
Change is maintainable and easy to review -
Reviewed by at least 1 teammate -
Reviewed by product owner
Edited by Lakshy Yarlagadda