Migrations
You added a field. The database does not know about it. Kewos offers two paths, and picking the wrong one is the most common way to lose a column.
Reconcile, or migrate
kewos reconcile | kewos migrate | |
|---|---|---|
| What it does | adds what is missing: tables, safe columns | applies a written file, whatever it says |
| What it never does | drop, rename, change a type | nothing: it does what the file says |
| Where it is used | on every deploy, across all tenants | when the change cannot be guessed |
Reconciliation is additive by construction. That is what lets you run it on every deploy without re-reading it: it cannot destroy, so it needs no approval.
Step 2 of the second walkthrough is the example: two fields contributed to an existing model, and nothing else to do.
main [active]: reconciled (0 migration(s), 2 column(s))Seeing the gap before touching it
kewos migrate plan --database-url "$KEWOS_DATABASE_URL" - DropTable: DropTable(table='gear_item') - AlterColumnType: AlterColumnType(table='esign_field', column='value_image', from_type='BYTEA', to_type='BLOB') - AddForeignKey: AddForeignKey(table='pipeline_lead', column='rivals_competitor_id', target_table='rivals_competitor', target_column='id', on_delete='SET NULL')That plan is real, and it deserves slow reading, because it holds three things of very different natures: a foreign key to create (harmless), a type to change (check it), and four tables to drop because their modules are no longer in the tree the command read.
A plan is a proposal, not a diagnosis. It compares the database to what the registry declares here and now; a module absent from the folder therefore looks like a deleted module.
Writing the file
kewos migrate generate \ --database-url "$KEWOS_DATABASE_URL" \ --module pipeline_rivals --revision 0001_rivals \ --description "add the competitor links" --output migrations/wrote migrations/0001_rivals.py (classification=destructive, down_revision=0001_reconcile_link)The word destructive is not decoration: it is computed from the operations, written into
the file, and it tells you to read it before applying it.
"""Auto-generated migration: add the competitor links.
Module: pipeline_rivalsClassification: destructive"""
revision = '0001_rivals'down_revision = '0001_reconcile_link'classification = 'destructive'
def upgrade() -> Migration: return ( Migration() .drop_table(table='gear_item') .add_foreign_key(table='pipeline_lead', column='rivals_competitor_id', target_table='rivals_competitor', target_column='id', on_delete='SET NULL') )
def downgrade() -> Migration: # TODO: downgrade for DropTable on 'gear_item' cannot be auto-generated # (data was lost); restore manually. return ( Migration() .drop_foreign_key(table='pipeline_lead', column='rivals_competitor_id', target_table='rivals_competitor', target_column='id') )The file reads, and the downgrade says what it cannot undo. Dropping a table cannot be
reversed: the data is gone. That TODO is not the generator being lazy, it is the only honest
answer.
Your job on this file: remove what you did not mean. Here, the four drop_table calls for
modules that live elsewhere.
auto only runs in development
kewos migrate auto ...MigrationGuardError: `kewos migrate auto` refuses to run outside development(KEWOS_ENV is 'production'). Run `generate` then `apply` explicitly.auto does the three gestures in a row: detect, write, apply. Convenient on your machine and
unacceptable anywhere else, because nobody read the file between the second and the third. The
guard refuses and names the way forward instead of just saying no.
The trap that tests cannot see
A model declaring a server-side default, and a migration that does not set it, make a silent pair: tests create their tables from the model, so they see the default and pass. Production has the table the migration created, without it, and the first insert relying on it fails.
The symptom is a green test and a 500 on the first real save. When you add a server_default,
check that the migration sets it too.
The order in production
- deploy the code;
kewos reconcile --confirm: the safe additions, across all tenants;kewos migrate applyonly for the files that could not be guessed, after reading them.
Never migrate auto. Never a schema auto-created from the models.