[IMP] migration: say when the COW question is actually asked

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
This commit is contained in:
Mathieu Benoit 2026-08-12 01:36:47 -04:00
parent fcfbcd25ce
commit 4ce612b008
3 changed files with 48 additions and 2 deletions

View file

@ -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"

View file

@ -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",

View file

@ -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}")