bug: non-idempotent division enum in migration 008 causes CrashLoopBackOff on deploy #85
Labels
No labels
domain:backend
domain:devops
domain:frontend
status:approved
status:in-progress
status:needs-fix
status:qa
type:bug
type:devops
type:feature
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
forgejo_admin/basketball-api#85
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Lineage
plan-2026-03-08-tryout-prep→ Phase 10a (Team model + assignment endpoints)Deployment blocker — migration 008 crashes on
alembic upgrade head.Repo
forgejo_admin/basketball-apiUser Story
As a platform operator
I want migrations to run idempotently on every pod restart
So that new deployments don't CrashLoopBackOff
Context
basketball-api is in CrashLoopBackOff after CI pushed a new image. The Dockerfile runs
alembic upgrade headbefore starting uvicorn. The DB is at revision007. Migration 008 (008_add_team_model.py) needs to run for the first time to create theteamstable.The migration correctly uses
postgresql.ENUM("boys", "girls", name="division", create_type=False)for the division column. However,alembic/env.pyimports all models and setstarget_metadata = Base.metadata. TheTeammodel inmodels.pydefinesdivisionasEnum(Division)(generic SQLAlchemy Enum withcreate_type=Truedefault). Whenop.create_table("teams")executes, SQLAlchemy's table creation events fire using the metadata's enum type (which hascreate_type=True), overriding the migration'screate_type=False. This issuesCREATE TYPE division AS ENUM ('boys', 'girls')without checking first — but the type already exists from migratione09c9e678004.Error:
File Targets
Files the agent should modify:
alembic/versions/008_add_team_model.py— replaceop.create_table()with raw SQL viaop.execute()to bypass SQLAlchemy's type creation event system. UseCREATE TABLE IF NOT EXISTSfor the teams table. Handleagegroupenum withDO $$ BEGIN ... EXCEPTION WHEN duplicate_object THEN null; END $$pattern. Keep theop.add_columnforplayers.team_idanddowngrade()as-is.Files the agent should NOT touch:
src/basketball_api/models.py— the model is correct, the bug is in the migrationalembic/env.py— metadata import is correct for autogenerateAcceptance Criteria
alembic upgrade headsucceeds from revision 007 without errorteamstable created with correct columns: id, tenant_id, name, division (division enum), age_group (agegroup enum), coach_id, created_atplayers.team_idFK column addedTest Expectations
pytest(242 tests)pytestConstraints
op.execute()with raw SQL for table creation — do NOT try to fix the SQLAlchemy metadata interactiondowngrade()function unchangedagegroupenum creation should also use the idempotentDO $$ BEGIN ... EXCEPTIONpatterntenant_idandcoach_id(create withop.create_indexor raw SQL)Checklist
Related
project-westside-basketball— deployment blocker for basketball-api