Make drop_team_data_source migration idempotent #479

Merged
johnsturgeon merged 1 commit from fix-drop-team-data-source-migration-idempotent into main 2026-09-06 19:53:10 +02:00
Owner

resolves #480

Problem

Production crashed running migrations:

sqlalchemy.exc.ProgrammingError: (psycopg.errors.UndefinedColumn)
column "data_source" of relation "team" does not exist
[SQL: ALTER TABLE team DROP COLUMN data_source]

The migration a390332fa722 ran an unconditional op.drop_column('team', 'data_source'), but no migration in the chain ever creates that column. The Alembic baseline (0c2ed4448b99) was auto-generated on 2026-08-31, after the Tank01 refactor (302663c, 2026-08-28) removed data_source from the Team model — so the baseline codifies a team table without the column. Any database built from the chain creates team without data_source and then tries to drop it → crash.

Fix

Use ALTER TABLE team DROP COLUMN IF EXISTS data_source, which:

  • drops the column on pre-baseline snapshots that still carry the ESPN-era field, and
  • is a safe no-op on any database built from the current baseline.

Version bumped 2.30.0 → 2.30.1. Tests: 314 passed, pylint 10.00/10.

🤖 Generated with Claude Code

resolves #480 ## Problem Production crashed running migrations: ``` sqlalchemy.exc.ProgrammingError: (psycopg.errors.UndefinedColumn) column "data_source" of relation "team" does not exist [SQL: ALTER TABLE team DROP COLUMN data_source] ``` The migration `a390332fa722` ran an **unconditional** `op.drop_column('team', 'data_source')`, but no migration in the chain ever creates that column. The Alembic baseline (`0c2ed4448b99`) was auto-generated on 2026-08-31, *after* the Tank01 refactor (`302663c`, 2026-08-28) removed `data_source` from the `Team` model — so the baseline codifies a `team` table without the column. Any database built from the chain creates `team` without `data_source` and then tries to drop it → crash. ## Fix Use `ALTER TABLE team DROP COLUMN IF EXISTS data_source`, which: - drops the column on pre-baseline snapshots that still carry the ESPN-era field, and - is a safe no-op on any database built from the current baseline. Version bumped 2.30.0 → 2.30.1. Tests: 314 passed, pylint 10.00/10. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Make drop_team_data_source migration idempotent
All checks were successful
Claude Code Review / claude-review (pull_request) Successful in 31s
Python FastAPI Jinja Linting / build (pull_request) Successful in 29s
Tests / pytest (pull_request) Successful in 16s
Release on merge / release (pull_request) Successful in 0s
e2ca9a6de3
The migration ran an unconditional DROP COLUMN, but the Alembic baseline
was regenerated after data_source was removed from the Team model, so
databases built from it never had the column. Production crashed with
UndefinedColumn on ALTER TABLE team DROP COLUMN data_source.

Use DROP COLUMN IF EXISTS so it drops the column on pre-baseline
snapshots that still carry it and is a no-op everywhere else.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

The team model has no data_source column (confirmed), and a390332fa722 is the head migration. The fix is sound.


This change makes a crash-on-deploy migration idempotent by switching an unconditional op.drop_column to ALTER TABLE team DROP COLUMN IF EXISTS data_source, which is correct PostgreSQL and safely no-ops on baseline-built databases while still dropping the column on pre-baseline snapshots. The diagnosis in the PR description matches the code, the version was bumped per convention (2.30.0 → 2.30.1 in both pyproject.toml and uv.lock), and this looks good to merge.

Nits

  • alembic/versions/a390332fa722_drop_team_data_source.py:33 — The downgrade() re-adds the column unconditionally, so it's now asymmetric with the idempotent upgrade(): on a database built from the current baseline the upgrade is a no-op, but a subsequent downgrade would create a data_source column that never existed there. This is harmless in practice (downgrading this migration is not something production does, and reverting to the "pre-migration state" is arguably the point), so it's not worth blocking on — but if you want strict symmetry, op.execute("ALTER TABLE team ADD COLUMN IF NOT EXISTS data_source VARCHAR NOT NULL DEFAULT ''") would mirror the guard.
<!-- claude-code-review --> The team model has no `data_source` column (confirmed), and `a390332fa722` is the head migration. The fix is sound. --- This change makes a crash-on-deploy migration idempotent by switching an unconditional `op.drop_column` to `ALTER TABLE team DROP COLUMN IF EXISTS data_source`, which is correct PostgreSQL and safely no-ops on baseline-built databases while still dropping the column on pre-baseline snapshots. The diagnosis in the PR description matches the code, the version was bumped per convention (`2.30.0 → 2.30.1` in both `pyproject.toml` and `uv.lock`), and this looks good to merge. ### Nits - `alembic/versions/a390332fa722_drop_team_data_source.py:33` — The `downgrade()` re-adds the column unconditionally, so it's now asymmetric with the idempotent `upgrade()`: on a database built from the current baseline the upgrade is a no-op, but a subsequent downgrade would *create* a `data_source` column that never existed there. This is harmless in practice (downgrading this migration is not something production does, and reverting to the "pre-migration state" is arguably the point), so it's not worth blocking on — but if you want strict symmetry, `op.execute("ALTER TABLE team ADD COLUMN IF NOT EXISTS data_source VARCHAR NOT NULL DEFAULT ''")` would mirror the guard.
johnsturgeon deleted branch fix-drop-team-data-source-migration-idempotent 2026-09-06 19:53:11 +02:00
Sign in to join this conversation.
No description provided.