From 1785a2019d2a07b82f205f9bc642af4e1980046c Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Wed, 19 Aug 2026 19:45:33 -0400 Subject: [PATCH] [FIX] script todo: nommer les outils qu'une VM sans ERPLibre ne peut pas poser MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Les outils de la phase « après » vivent DANS le dépôt : la compilation mobile, l'AVD, et maintenant le script Forgejo. Sur une VM « bureau seul », sans clone, ils n'existent pas — et ils étaient écartés en silence. Une case cochée passait donc pour honorée. La commande le dit désormais, en nommant les outils concernés. Trois lignes qui évitent de chercher pourquoi la forge demandée n'est nulle part. --- EN --- The "after" phase tools live IN the repository: the mobile build, the AVD, and now the Forgejo script. On a desktop-only VM, with no clone, they do not exist — and they were dropped in silence. A ticked checkbox therefore passed for honoured. The command now says so, naming the tools concerned. Three lines that save hunting for why the requested forge is nowhere to be found. Assisted-by: Claude Opus 5 --- script/todo/todo.py | 16 ++++++++++++++++ script/todo/todo_i18n.py | 4 ++++ test/test_qemu_forgejo.py | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/script/todo/todo.py b/script/todo/todo.py index e24423b..76143b0 100755 --- a/script/todo/todo.py +++ b/script/todo/todo.py @@ -6686,12 +6686,28 @@ class TODO: # sans quoi le verrou apt ferait échouer l'installation du bureau. if not desktop: return "true" + # Les outils de la phase « after » vivent DANS le dépôt — la + # compilation mobile, l'AVD, le script Forgejo. Sans clone, ils + # n'existent pas ici. Les écarter en silence laissait croire qu'une + # case cochée avait été honorée : on la NOMME. + deferred = [ + k + for k in (tools or ()) + if self._QEMU_VM_TOOLS.get(k, {}).get("phase") == "after" + ] + note = ( + f'echo " ⚠ {t("needs the ERPLibre install, skipped:")}' + f' {" ".join(deferred)}"; ' + if deferred + else "" + ) return ( "set -e; " + self._qemu_cloud_init_wait() + self._qemu_no_auto_upgrade(prod, app_store) + self._qemu_desktop_remote_cmd(desktop, app_store) + self._qemu_tools_remote_cmd(tools, prod) + + note ) if not final_cmd: final_cmd = f"make install_os && make {self.ERPLIBRE_ODOO_TARGET}" diff --git a/script/todo/todo_i18n.py b/script/todo/todo_i18n.py index 699f631..22abfc6 100644 --- a/script/todo/todo_i18n.py +++ b/script/todo/todo_i18n.py @@ -2260,6 +2260,10 @@ TRANSLATIONS = { "line": {"fr": "ligne", "en": "line"}, "free space": {"fr": "libre", "en": "free"}, "silent": {"fr": "silence", "en": "silent"}, + "needs the ERPLibre install, skipped:": { + "fr": "exige l'installation ERPLibre, écarté :", + "en": "needs the ERPLibre install, skipped:", + }, "Forgejo (git forge)": { "fr": "Forgejo (forge git)", "en": "Forgejo (git forge)", diff --git a/test/test_qemu_forgejo.py b/test/test_qemu_forgejo.py index be385af..c50bba0 100644 --- a/test/test_qemu_forgejo.py +++ b/test/test_qemu_forgejo.py @@ -135,6 +135,38 @@ class TestTheInstallBlock(unittest.TestCase): self.assertEqual(0, res.returncode, f"{tools}: {res.stderr}") +class TestDesktopOnlyVm(unittest.TestCase): + """Une VM sans ERPLibre : le script Forgejo vit dans le dépôt, donc nulle + part. L'écarter en silence laisserait croire qu'une case cochée a été + honorée.""" + + def setUp(self): + self.todo = TODO.__new__(TODO) + + def test_it_says_what_it_skips(self): + cmd = self.todo._qemu_erplibre_remote_cmd( + None, None, False, "gnome", "", "deb", ("forgejo",) + ) + self.assertIn("forgejo", cmd) + self.assertIn("⚠", cmd) + self.assertNotIn("install_forgejo.sh", cmd) + + def test_it_stays_quiet_when_nothing_was_deferred(self): + cmd = self.todo._qemu_erplibre_remote_cmd( + None, None, False, "gnome", "", "deb", ("gnome_ext",) + ) + self.assertNotIn("⚠", cmd) + + def test_the_note_is_valid_shell(self): + cmd = self.todo._qemu_erplibre_remote_cmd( + None, None, False, "gnome", "", "deb", ("forgejo", "mobile") + ) + res = subprocess.run( + ["bash", "-n"], input=cmd, capture_output=True, text=True + ) + self.assertEqual(0, res.returncode, res.stderr) + + class TestTheScript(unittest.TestCase): """Le script lui-même, exécuté sur ses chemins de refus."""