fix(migrations): make the ui_use_tailwind removal idempotent - #15842
Merged
Conversation
0293_remove_usercontactinfo_ui_use_tailwind used a plain RemoveField, which emits an unconditional `ALTER TABLE ... DROP COLUMN` and fails with `column "ui_use_tailwind" of relation "dojo_usercontactinfo" does not exist` whenever the column is not physically present when the migration runs — which the OSS->Pro upgrade path hits (the upgrade fixture reaches 0293 without the column), and which any instance with migration-history/schema skew can hit too. Split the operation into SeparateDatabaseAndState: keep the state RemoveField so Django's model state is unchanged (no new migration is generated), and make the database drop idempotent with `DROP COLUMN IF EXISTS`. UserContactInfo is not pghistory-tracked, so no event table carries the column and a raw ALTER TABLE is sufficient. Mirrors the existing SeparateDatabaseAndState removal pattern in 0266_remove_credential_manager. The reverse re-adds the column with its original 0267 definition. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
blakeaowens
approved these changes
Sep 1, 2026
devGregA
approved these changes
Sep 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Shortcut: sc-14995
Description
0293_remove_usercontactinfo_ui_use_tailwindremoves theui_use_tailwindopt-in (added in0267) with a plainRemoveField. That emits an unconditionalALTER TABLE dojo_usercontactinfo DROP COLUMN ui_use_tailwind, which fails when the column is not physically present at the moment the migration runs:This is reachable on the upgrade path — a database can arrive at
0293without the column present when its recorded migration history skews from its physical schema (e.g. the column addition never materialized in that DB even though later history is applied). A plainRemoveFieldcannot tolerate that, and the whole migrate run aborts.Fix
Split the operation into
SeparateDatabaseAndState:RemoveField, so Django's model state is unchanged — no new migration is generated, and the model no longer defines the field.ALTER TABLE ... DROP COLUMN IF EXISTS, so the drop is a no-op when the column is already gone instead of an error.UserContactInfois not pghistory-tracked, so no event table carries the column and a rawALTER TABLEis sufficient. This mirrors the existingSeparateDatabaseAndStateremoval pattern in0266_remove_credential_manager. The reverse re-adds the column with its original0267definition (BooleanField(default=False)) so a downgrade restores a working schema.Validation
ALTER TABLE ... DROP COLUMNon an absent column raisescolumn "ui_use_tailwind" ... does not exist, whileDROP COLUMN IF EXISTSemits a skipNOTICEand succeeds.state_operationsis an identicalRemoveField, so the model-state result is unchanged (nomakemigrationsdrift).dojo/db_migrations, which is excluded from the ruff lint config.