[ADD] migration: measure the public URLs before the first bump too

Without a starting point, a page that already answered 500 reads as
damage done by the migration, and the search goes the wrong way for
hours. Measured on the real one: two URLs were already failing before
anything had been migrated.

Asked in step 2, on the database before the bump — not on a bump
database that does not exist yet — and it says what it measures: a page
broken now will still be broken after, and that is not the migration.

--- FR ---

[ADD] migration : mesurer les URL publiques avant le premier palier aussi

Sans point de départ, une page qui rendait déjà 500 se lit comme un
dégât de la migration, et l'on cherche des heures du mauvais côté.
Mesuré sur la vraie : deux URL cassaient avant que quoi que ce soit
n'ait été migré.

Posée à l'étape 2, sur la base d'avant le palier — pas sur une base de
palier qui n'existe pas encore — et elle dit ce qu'elle mesure : une
page cassée maintenant le sera encore après, et ce ne sera pas la
migration.

Assisted-by: Claude Opus 5
This commit is contained in:
Mathieu Benoit 2026-08-17 05:13:13 -04:00
parent ec29781b7a
commit 2eac9e9848
3 changed files with 88 additions and 3 deletions

View file

@ -5082,6 +5082,18 @@ TRANSLATIONS = {
"fr": "(un palier de version) ou quand la page est rendue.",
"en": "(a version bump) or when the page is rendered.",
},
"Before starting: what already answers, and what": {
"fr": "Avant de commencer : ce qui répond déjà, et ce qui",
"en": "Before starting: what already answers, and what",
},
"does not. A page broken now will still be broken": {
"fr": "ne répond pas. Une page cassée maintenant le sera encore",
"en": "does not. A page broken now will still be broken",
},
"after — and that is not the migration.": {
"fr": "après — et ce ne sera pas la migration.",
"en": "after — and that is not the migration.",
},
"Nothing to decide yet": {
"fr": "Rien à décider pour l'instant",
"en": "Nothing to decide yet",

View file

@ -1695,6 +1695,12 @@ class TodoUpgrade:
f" -d {database_name} -t odoo{start_version + 1}.0 --report-only"
)
# La mesure de DÉPART. Sans elle, une page qui rendait déjà 500 avant
# la migration se lit comme un dégât de la migration, et l'on cherche
# des heures du côté du palier. Mesuré : deux URL cassaient avant même
# de commencer.
self.prompt_smoke_public_url(database_name, baseline=True)
msg = "3 - Clean up database before data migration"
self.print_step(msg)
self.add_comment_progression(msg)
@ -2907,17 +2913,27 @@ class TodoUpgrade:
f" -d {database_name} {args} --apply"
)
def prompt_smoke_public_url(self, database_name):
def prompt_smoke_public_url(self, database_name, baseline=False):
"""Proposer d'interroger toutes les pages publiques de la base.
La liste vient du sitemap — celle qu'Odoo publie pour les moteurs de
recherche. Une page qui y figure et ne répond pas est une page que
les visiteurs n'atteignent pas non plus.
`baseline` marque la mesure d'AVANT le premier palier. Elle ne sert
pas à réparer — elle sert à savoir ce qui cassait déjà. Sans ce point
de départ, les mêmes 500 après le palier passent pour un dégât de la
migration, et l'on cherche du mauvais côté.
« non » par défaut : cela démarre un serveur et peut prendre quelques
minutes sur un gros site, et rien n'oblige à le faire à chaque
palier.
minutes sur un gros site.
"""
if baseline:
print(
f"\n✨ {t('Before starting: what already answers, and what')}"
f" {t('does not. A page broken now will still be broken')}"
f" {t('after — and that is not the migration.')}"
)
answer = (
self.ask_gate(
f"💬 {t('Request every public URL of this database now?')}"

View file

@ -365,6 +365,63 @@ class TestTheMigrationOffersIt(unittest.TestCase):
self.assertIn("smoke_public_url.py", lst_cmd[0])
self.assertIn("-d db_upgrade_13", lst_cmd[0])
def test_it_is_also_asked_before_the_first_bump(self):
# LA mesure de départ : sans elle, une page qui rendait déjà 500
# avant la migration se lit comme un dégât du palier, et l'on
# cherche des heures du mauvais côté.
import inspect
from script.todo.todo_upgrade import TodoUpgrade
source = inspect.getsource(TodoUpgrade.execute_odoo_upgrade)
self.assertEqual(source.count("prompt_smoke_public_url"), 2)
premier = source.index("prompt_smoke_public_url")
self.assertLess(
premier, source.index("4 - Upgrade version with OpenUpgrade")
)
def test_the_baseline_runs_on_the_database_before_the_bump(self):
# Sur la base d'AVANT, pas sur une base de palier qui n'existe pas
# encore : la mesurer après ne dirait plus d'où vient la panne.
import inspect
from script.todo.todo_upgrade import TodoUpgrade
source = inspect.getsource(TodoUpgrade.execute_odoo_upgrade)
premier = source.index("prompt_smoke_public_url")
fenetre = source[premier : premier + 90]
self.assertIn("database_name", fenetre)
self.assertNotIn("database_name_upgrade", fenetre)
self.assertIn("baseline=True", fenetre)
def test_the_baseline_says_what_it_measures(self):
# Un même écran à deux moments différents : sans un mot, on croit
# que la migration a déjà eu lieu.
import contextlib
import io
from script.todo import todo_i18n
from script.todo.todo_upgrade import TodoUpgrade
self.addCleanup(
setattr, todo_i18n, "_current_lang", todo_i18n._current_lang
)
todo_i18n._current_lang = "en"
upgrade = TodoUpgrade.__new__(TodoUpgrade)
upgrade.dct_progression = {}
upgrade.lst_command_executed = []
upgrade.write_config = lambda: None
upgrade.run_on_terminal = lambda cmd: 0
upgrade.ask_gate = lambda prompt: ""
out = io.StringIO()
with contextlib.redirect_stdout(out):
upgrade.prompt_smoke_public_url("db", baseline=True)
self.assertIn("Before starting", out.getvalue())
out = io.StringIO()
with contextlib.redirect_stdout(out):
upgrade.prompt_smoke_public_url("db")
self.assertNotIn("Before starting", out.getvalue())
def test_it_is_asked_before_the_selenium_prompt(self):
# Après, la question arriverait une fois le navigateur ouvert : on
# aurait déjà cherché à la main ce que le test nomme.