From 4ce612b0084b41a826b4fe5967c18cb4e1094e96 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Wed, 12 Aug 2026 01:36:47 -0400 Subject: [PATCH] [IMP] migration: say when the COW question is actually asked MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An early check warns, hours before the bump, that a copy will break it. It then says « arbitrate BEFORE launching the migration » and hands over a raw UPDATE — and no question follows. Read on a resumed run it looks like the question already went by and was skipped, which is exactly how it was read. It now says the migration asks at the bump itself, and shows what each copy holds before the answer. The manual UPDATE stays, but after the two commands that do it reversibly: telling someone to hand-write SQL when --restore exists is offering the sharper tool first. --- FR --- Un contrôle précoce prévient, des heures avant le palier, qu'une copie va le casser. Il dit ensuite « arbitrez AVANT de lancer la migration » et livre un UPDATE brut — et aucune question ne suit. Lu au cours d'une reprise, on croit que la question est passée et a été sautée, ce qui est exactement la lecture qui en a été faite. Il dit maintenant que la migration pose la question au palier lui-même, en montrant ce que chaque copie contient avant qu'on réponde. L'UPDATE manuel reste, mais après les deux commandes qui le font de façon réversible : dire à quelqu'un d'écrire du SQL à la main quand --restore existe, c'est tendre l'outil le plus coupant en premier. Assisted-by: Claude Opus 5 --- script/odoo/migration/check_cow_views.py | 10 ++++++++- script/todo/todo_i18n.py | 27 ++++++++++++++++++++++++ script/todo/todo_upgrade.py | 13 +++++++++++- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/script/odoo/migration/check_cow_views.py b/script/odoo/migration/check_cow_views.py index 07321a0..d01d2fa 100755 --- a/script/odoo/migration/check_cow_views.py +++ b/script/odoo/migration/check_cow_views.py @@ -313,7 +313,15 @@ def main(): f" : {mode} -> {target_mode} ({reason})" ) print( - " Arbitrate BEFORE launching the migration. To neutralize a copy," + " The migration will offer to neutralize them at the bump, and" + " shows what each copy holds before you answer. To do it now:" + "\n ./script/odoo/migration/cow_drift.py -d DB -t odooXX.0" + " (read what they hold)" + "\n ./script/odoo/migration/neutralize_cow_views.py -d DB" + " -t odooXX.0 --apply (reversible with --restore)" + ) + print( + " Or by hand. To neutralize a copy," " rename its key (UPDATE ir_ui_view SET key='zz_cow_archive.'||key," " active=false): an unmatched key is never paired with the module" " view, so the copy never receives the new inherit_id. Setting" diff --git a/script/todo/todo_i18n.py b/script/todo/todo_i18n.py index ef08606..8e83355 100644 --- a/script/todo/todo_i18n.py +++ b/script/todo/todo_i18n.py @@ -3872,6 +3872,33 @@ TRANSLATIONS = { "fr": "faite plus tôt, avant la neutralisation", "en": "done early, before the neutralization", }, + "compare each website copy with the module view it shadows": { + "fr": "comparer chaque copie de site web à la vue de module qu'elle" + " masque", + "en": "compare each website copy with the module view it shadows", + }, + "Compare the website copies with the view they shadow": { + "fr": "🪞 Comparer les copies de site web à la vue qu'elles masquent", + "en": "🪞 Compare the website copies with the view they shadow", + }, + "website copies compared with their module view,": { + "fr": "copies de site web comparées à leur vue de module,", + "en": "website copies compared with their module view,", + }, + "differ.": {"fr": "diffèrent.", "en": "differ."}, + "Nothing to decide yet": { + "fr": "Rien à décider pour l'instant", + "en": "Nothing to decide yet", + }, + "the migration will offer to neutralize these copies": { + "fr": "la migration proposera de neutraliser ces copies", + "en": "the migration will offer to neutralize these copies", + }, + "at the version bump itself, showing what each one holds.": { + "fr": "au moment du palier lui-même, en montrant ce que chacune" + " contient.", + "en": "at the version bump itself, showing what each one holds.", + }, # --- script/analyse : vues personnalisées --- "Customised views": { "fr": "Vues personnalisées", diff --git a/script/todo/todo_upgrade.py b/script/todo/todo_upgrade.py index c75a592..0daace6 100755 --- a/script/todo/todo_upgrade.py +++ b/script/todo/todo_upgrade.py @@ -1457,11 +1457,22 @@ class TodoUpgrade: # -- before hours of migration -- leaves time to arbitrate. # Only the next bump can be predicted: the modes in database describe # the current version. - self.todo_upgrade_execute( + status, cmd_executed, output = self.todo_upgrade_execute( f"{PYTHON_BIN} ./script/odoo/migration/check_cow_views.py" f" -d {database_name} -t odoo{start_version + 1}.0", + get_output=True, wait_at_error=False, ) + # Cet avertissement n'est qu'un avertissement, et rien ne le disait : + # il annonce un problème, propose d'arbitrer, et aucune question ne + # suit. On en conclut que la question est passée — alors qu'elle vient + # au moment du palier, des dizaines de minutes plus tard. + if output and "will break when moving to" in "\n".join(output): + print( + f"ℹ -> {t('Nothing to decide yet')} :" + f" {t('the migration will offer to neutralize these copies')}" + f" {t('at the version bump itself, showing what each one holds.')}" + ) msg = "3 - Clean up database before data migration" print(f"🔷 {msg}")