Les migrations
Vous avez ajouté un champ. La base ne le connaît pas. Kewos offre deux chemins, et choisir le mauvais est la façon la plus courante de perdre une colonne.
Rapprocher, ou migrer
kewos reconcile | kewos migrate | |
|---|---|---|
| Ce qu’il fait | ajoute ce qui manque : tables, colonnes sûres | applique un fichier écrit, quel qu’il soit |
| Ce qu’il ne fait jamais | supprimer, renommer, changer un type | rien : il fait ce que le fichier dit |
| Où on l’utilise | à chaque déploiement, sur tous les tenants | quand le changement ne peut pas être deviné |
Le rapprochement est additif par construction. C’est ce qui permet de le lancer à chaque déploiement sans le relire : il ne peut pas détruire, donc il n’a pas besoin d’être approuvé.
L’étape 2 du second parcours en est l’exemple : deux champs contribués à un modèle existant, et rien d’autre à faire.
main [active]: reconciled (0 migration(s), 2 column(s))Voir l’écart avant d’y toucher
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')Ce plan est réel, et il mérite d’être lu lentement, parce qu’il contient trois choses de natures très différentes : une clé étrangère à créer (inoffensif), un type à changer (à vérifier), et quatre tables à supprimer parce que leurs modules ne sont plus dans l’arbre lu par la commande.
Un plan est une proposition, pas un diagnostic. Il compare la base à ce que le registre déclare ici et maintenant ; un module absent du dossier ressemble donc à un module supprimé.
Écrire le fichier
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)Le mot destructive n’est pas décoratif : il est calculé à partir des opérations, il est
écrit dans le fichier, et il vous dit qu’il faut le lire avant de l’appliquer.
"""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') )Le fichier se lit, et le retour arrière dit ce qu’il ne sait pas défaire. Une suppression
de table ne se déjoue pas : la donnée n’est plus là. Ce TODO n’est pas une négligence du
générateur, c’est la seule réponse honnête.
Votre travail sur ce fichier : retirer ce que vous n’avez pas voulu. Ici, les quatre
drop_table de modules qui existent ailleurs.
auto ne tourne qu’en développement
kewos migrate auto ...MigrationGuardError: `kewos migrate auto` refuses to run outside development(KEWOS_ENV is 'production'). Run `generate` then `apply` explicitly.auto fait les trois gestes d’affilée : détecter, écrire, appliquer. C’est pratique sur votre
poste et inacceptable ailleurs, parce que personne n’a lu le fichier entre le deuxième et le
troisième. Le garde-fou refuse et nomme la marche à suivre au lieu de dire non.
Le piège qui ne se voit pas en test
Un modèle qui déclare une valeur par défaut au niveau serveur et une migration qui ne la pose pas donnent un couple silencieux : les tests créent leurs tables depuis le modèle, donc ils voient la valeur par défaut et passent. La production, elle, a la table créée par la migration, sans la valeur : la première insertion qui compte sur elle échoue.
Le symptôme est un test vert et une erreur 500 au premier enregistrement réel. Quand vous
ajoutez un server_default, vérifiez que la migration le pose aussi.
L’ordre en production
- déployer le code ;
kewos reconcile --confirm: les ajouts sûrs, sur tous les tenants ;kewos migrate applyseulement pour les fichiers qui ne pouvaient pas être devinés, après lecture.
Jamais migrate auto. Jamais un schéma créé automatiquement à partir des modèles.