fix(migrations): widen alembic_version.version_num so long revision ids stamp on PostgreSQL (#1420)#1421
Conversation
…ds stamp on PostgreSQL (#1420) P0 — backend failed to boot on every PostgreSQL instance. Alembic auto-creates `alembic_version.version_num` as VARCHAR(32) (its historical default), but Trinity's descriptive `NNNN_<table>_<change>` revision ids exceed that (`0009_agent_ownership_public_channel_model` = 41). PostgreSQL enforces the width, so the version-stamp UPDATE raised StringDataRightTruncation, the backend never went healthy, and `depends_on: service_healthy` took frontend/mcp/scheduler down with it. SQLite doesn't enforce VARCHAR length, so SQLite-only CI never saw it. Fix (widen to VARCHAR(255), no revision renames): - New migration `0008a_widen_alembic_version` (slotted before 0009, which is rechained onto it) ALTERs the column on existing PG DBs — its own id is ≤32 so it stamps fine on the still-narrow column, then widens it. No-op on non-PG. - `env.py` sets `version_table_column_type=String(255)` so fresh builds auto-create the table wide; `0001_baseline` downgrade DDL matches. Regression guards (both requested in the issue): - `.github/workflows/pg-migrations.yml` — runs a REAL `alembic upgrade head` against postgres:16, seeding a narrow (32) alembic_version first to reproduce the exact outage path, and asserts head + width≥255. Advisory (not required) so an infra hiccup can't brick the queue. - `tests/unit/test_alembic_revision_id_length.py` — lints every revision id ≤255 and keeps env.py/baseline widths in lockstep (runs in the SQLite lane). Verified end-to-end against the running trinity-postgres (16): reproduced the narrow-column outage, then upgraded a from-base DB through 0008→0008a→0009(41 chars)→0010(head) with the column widened to varchar(255); fresh auto-create also lands at 255. Scratch DBs cleaned up. Closes #1420 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
/review ReportBranch: Scope check
Critical findings (block merge)None. Verified:
Informational findings (review recommended)[I1] CI: [I2] CI: Python-dependency surface is unproven (Confidence: 5/10 — appendix) [I3] Naming: Clean categoriesRace/concurrency (migrations run under the #1160 Summary
Durable learning (for /autoplan)Every Alembic schema change needs a real-PostgreSQL CI run, not just SQLite: SQLite silently ignores 🤖 Generated with Claude Code |
vybe
left a comment
There was a problem hiding this comment.
P0 PostgreSQL boot fix. Validated: migration chain is linear/single-head; the width-widen (0008a) sequences correctly before 0009's 41-char id stamp; SQLite track correctly untouched (Invariant #3); regression test + advisory pg-migrations CI guard both name #1420 and pass; all 4 required checks green. Approving.
P0 outage fix. On every PostgreSQL instance the backend fails to boot:
alembic upgrade headaborts on migration0009because its 41-char id0009_agent_ownership_public_channel_modeldoesn't fitalembic_version.version_num, which Alembic auto-creates asVARCHAR(32). PostgreSQL enforces the width →StringDataRightTruncation→ backend never healthy →depends_on: service_healthytakes frontend/mcp/scheduler down too. SQLite doesn't enforceVARCHARlength, so SQLite-only CI never caught it.Fix (widen to
VARCHAR(255)— no revision renames)0008a_widen_alembic_version— new migration slotted before0009(which is rechained onto it). Its own id is ≤32 so it stamps fine on the still-narrow column, thenALTERs the column to 255 on PostgreSQL. No-op on SQLite/other dialects and on already-wide columns. Fixes existing PG DBs on their next upgrade.env.pysetsversion_table_column_type=String(255)so fresh builds auto-create the version table wide;0001_baselinedowngrade DDL matches.Regression guards (both requested in the issue)
.github/workflows/pg-migrations.yml— the guard that would've caught this: runs a realalembic upgrade headagainstpostgres:16, seeding a narrow (32)alembic_versionfirst to reproduce the exact outage path, then asserts head is reached and width ≥255. Advisory (not a required check) so an infra hiccup can't brick the merge queue.tests/unit/test_alembic_revision_id_length.py— lints every revision id ≤255 and keeps the env.py/baseline widths in lockstep (runs in the existing SQLite lane).Verification — end-to-end on real PostgreSQL 16
Against the running
trinity-postgres(whose livealembic_versionis indeedvarchar(32)):0008→ upgrade → hit the truncation point.0008 → 0008a_widen → 0009 (41 chars) → 0010 (head)and the column is nowvarchar(255).varchar(255)viaenv.pyand reaches0010.alembic heads→0010). Scratch DBs cleaned up.Unit: 41 passing across the new lint +
test_schema_parity+test_alembic_parity_guard. Migration is PG-guarded so the SQLite track is untouched;check_alembic_parity.pyis satisfied (nodb/{schema,tables,migrations}.pyDDL added).Fixes #1420
🤖 Generated with Claude Code