From aa94e460ec55917d8eb2db6a2a8a302376d980ba Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Wed, 19 Aug 2026 05:57:22 -0400 Subject: [PATCH] =?UTF-8?q?[FIX]=20script=20todo:=20ne=20plus=20empaqueter?= =?UTF-8?q?=20les=20d=C3=A9p=C3=B4ts=20du=20manifeste=20dans=20l'APK?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit La compilation butait sur « Too many zip entries 123678 (MAX=65535) » : un APK est un ZIP, et le dépôt mobile verse 122 684 fichiers d'assets pour 337 qui sont l'application. Le levier existe et il est documenté chez lui (doc/SERVICES.md) : ERPLIBRE_MANIFEST_PATH, ici pointé sur un manifeste vide — « ces dépôts-là : aucun ». Le plugin l'annonce, « 0 repos ». Mesuré sur erplibre-ubuntu-2604-gnome : dist passe de 123 019 fichiers à 336, l'APK sort à 59 Mo et 2 472 entrées, et la phase mobile entière rend 0, tests Vitest compris — 75 fichiers, 1938 tests. Qui veut les dépôts pose la variable lui-même : elle est respectée. Mesure d'attente, à retirer quand ils tiendront sous le plafond du ZIP. --- EN --- The build hit "Too many zip entries 123678 (MAX=65535)": an APK is a ZIP, and the mobile repo pours 122,684 asset files in for 337 that are the application. The lever exists and that repo documents it (doc/SERVICES.md): ERPLIBRE_MANIFEST_PATH, pointed here at an empty manifest — "those repos: none". The plugin says so itself, "0 repos". Measured on erplibre-ubuntu-2604-gnome: dist drops from 123,019 files to 336, the APK comes out at 59 MB with 2,472 entries, and the whole mobile phase returns 0, Vitest included — 75 files, 1938 tests. Set the variable yourself and the repos come back. A stopgap, to drop once they fit under the ZIP ceiling. Assisted-by: Claude Opus 5 --- script/qemu/README.base.md | 32 ++++++++++++++++++++++++-------- script/qemu/README.fr.md | 17 +++++++++++++---- script/qemu/README.md | 15 +++++++++++---- script/todo/todo.py | 26 +++++++++++++++++++++++++- script/todo/todo_i18n.py | 4 ++++ test/test_qemu_desktop_tools.py | 27 +++++++++++++++++++++++++++ 6 files changed, 104 insertions(+), 17 deletions(-) diff --git a/script/qemu/README.base.md b/script/qemu/README.base.md index dacc1ca..14496b3 100644 --- a/script/qemu/README.base.md +++ b/script/qemu/README.base.md @@ -302,10 +302,17 @@ the dashboard, and the log names the probable cause instead of leaving a 40 MB Gradle log to read: disk full, missing SDK platform, JDK/Gradle mismatch, unaccepted licences, a Gradle daemon killed by the kernel (with the machine's RAM, swap and oom-kill count, because a memory cause is proven and -not assumed), or too many asset files for one APK — a ZIP holds 65535 entries -and the mobile repo ships 122 684, which only that repo can fix. The heavy -output goes to `~/erplibre-mobile-build.log` inside the VM so the install log -stays readable. +not assumed), or too many asset files for one APK. The heavy output goes to +`~/erplibre-mobile-build.log` inside the VM so the install log stays readable. + +That last cause no longer stops the build. The mobile repo bundles the manifest +repositories into its assets — 122 684 files, for 337 that are the application +— and an APK is a ZIP, capped at 65535 entries: `Too many zip entries 123678`. +The build therefore points `ERPLIBRE_MANIFEST_PATH`, the lever that repo +documents, at an empty manifest, and the plugin says so: `0 repos`. Measured: +`dist` drops from 123 019 files to 336, and the APK comes out at 59 MB with +2 472 entries. Set the variable yourself and the repositories come back — the +default is a stopgap until they fit under the ZIP ceiling. It is bounded to apt-based distributions, because that upstream installer starts with `sudo apt install openjdk-17-jdk`. It requires no Android Studio @@ -439,10 +446,19 @@ NOMME la cause probable au lieu de laisser 40 Mo de journal Gradle à relire : disque plein, plateforme SDK absente, JDK et Gradle incompatibles, licences non acceptées, démon Gradle tué par le noyau (avec la RAM, le swap et le compte de l'oom-killer, parce qu'une cause « mémoire » se prouve au lieu de s'affirmer), -ou trop de fichiers d'assets pour un APK — un ZIP tient 65535 entrées et le -dépôt mobile en embarque 122 684, ce que lui seul peut corriger. Le détail va -dans `~/erplibre-mobile-build.log`, dans la VM, pour que le journal -d'installation reste lisible. +ou trop de fichiers d'assets pour un APK. Le détail va dans +`~/erplibre-mobile-build.log`, dans la VM, pour que le journal d'installation +reste lisible. + +Cette dernière cause n'arrête plus la compilation. Le dépôt mobile empaquette +les dépôts du manifeste dans ses assets — 122 684 fichiers, pour 337 qui sont +l'application — et un APK est un ZIP, borné à 65535 entrées : +`Too many zip entries 123678`. La compilation pointe donc +`ERPLIBRE_MANIFEST_PATH`, le levier que ce dépôt documente, sur un manifeste +vide, et le plugin l'annonce : `0 repos`. Mesuré : `dist` passe de 123 019 +fichiers à 336, et l'APK sort à 59 Mo et 2 472 entrées. Posez la variable +vous-même et les dépôts reviennent — le défaut est une mesure d'attente, le +temps qu'ils tiennent sous le plafond du ZIP. Il est borné aux distributions apt, parce que cet installateur amont commence par `sudo apt install openjdk-17-jdk`. Il n'exige PAS Android Studio — une diff --git a/script/qemu/README.fr.md b/script/qemu/README.fr.md index 7263e25..dfe74d7 100644 --- a/script/qemu/README.fr.md +++ b/script/qemu/README.fr.md @@ -191,10 +191,19 @@ NOMME la cause probable au lieu de laisser 40 Mo de journal Gradle à relire : disque plein, plateforme SDK absente, JDK et Gradle incompatibles, licences non acceptées, démon Gradle tué par le noyau (avec la RAM, le swap et le compte de l'oom-killer, parce qu'une cause « mémoire » se prouve au lieu de s'affirmer), -ou trop de fichiers d'assets pour un APK — un ZIP tient 65535 entrées et le -dépôt mobile en embarque 122 684, ce que lui seul peut corriger. Le détail va -dans `~/erplibre-mobile-build.log`, dans la VM, pour que le journal -d'installation reste lisible. +ou trop de fichiers d'assets pour un APK. Le détail va dans +`~/erplibre-mobile-build.log`, dans la VM, pour que le journal d'installation +reste lisible. + +Cette dernière cause n'arrête plus la compilation. Le dépôt mobile empaquette +les dépôts du manifeste dans ses assets — 122 684 fichiers, pour 337 qui sont +l'application — et un APK est un ZIP, borné à 65535 entrées : +`Too many zip entries 123678`. La compilation pointe donc +`ERPLIBRE_MANIFEST_PATH`, le levier que ce dépôt documente, sur un manifeste +vide, et le plugin l'annonce : `0 repos`. Mesuré : `dist` passe de 123 019 +fichiers à 336, et l'APK sort à 59 Mo et 2 472 entrées. Posez la variable +vous-même et les dépôts reviennent — le défaut est une mesure d'attente, le +temps qu'ils tiennent sous le plafond du ZIP. Il est borné aux distributions apt, parce que cet installateur amont commence par `sudo apt install openjdk-17-jdk`. Il n'exige PAS Android Studio — une diff --git a/script/qemu/README.md b/script/qemu/README.md index cc035f3..81f673c 100644 --- a/script/qemu/README.md +++ b/script/qemu/README.md @@ -176,10 +176,17 @@ the dashboard, and the log names the probable cause instead of leaving a 40 MB Gradle log to read: disk full, missing SDK platform, JDK/Gradle mismatch, unaccepted licences, a Gradle daemon killed by the kernel (with the machine's RAM, swap and oom-kill count, because a memory cause is proven and -not assumed), or too many asset files for one APK — a ZIP holds 65535 entries -and the mobile repo ships 122 684, which only that repo can fix. The heavy -output goes to `~/erplibre-mobile-build.log` inside the VM so the install log -stays readable. +not assumed), or too many asset files for one APK. The heavy output goes to +`~/erplibre-mobile-build.log` inside the VM so the install log stays readable. + +That last cause no longer stops the build. The mobile repo bundles the manifest +repositories into its assets — 122 684 files, for 337 that are the application +— and an APK is a ZIP, capped at 65535 entries: `Too many zip entries 123678`. +The build therefore points `ERPLIBRE_MANIFEST_PATH`, the lever that repo +documents, at an empty manifest, and the plugin says so: `0 repos`. Measured: +`dist` drops from 123 019 files to 336, and the APK comes out at 59 MB with +2 472 entries. Set the variable yourself and the repositories come back — the +default is a stopgap until they fit under the ZIP ceiling. It is bounded to apt-based distributions, because that upstream installer starts with `sudo apt install openjdk-17-jdk`. It requires no Android Studio diff --git a/script/todo/todo.py b/script/todo/todo.py index 568528c..9d2696b 100755 --- a/script/todo/todo.py +++ b/script/todo/todo.py @@ -6260,10 +6260,34 @@ class TODO: "else sudo rm -f /swapfile-erplibre 2>/dev/null; " f'echo " {t("no swap could be added; build may run short")}"; ' "fi; fi; " + f'echo " {t("manifest repos not bundled (ZIP entry limit)")}"; ' f'mstep "{t("npm dependencies")}" ' f"'cd {el_dir}/mobile/erplibre_home_mobile && npm ci' && " + # L'empaquetage des dépôts du manifeste est DÉSACTIVÉ, et c'est + # une mesure d'attente. Il verse 122 684 fichiers dans les assets — + # des dépôts Odoo entiers, pour 337 qui sont l'application — et un + # APK est un ZIP : « Too many zip entries 123678 (MAX=65535) », la + # compilation s'arrête là. Les mêmes fichiers épuisaient aussi les + # watches inotify de l'IDE. + # + # Le levier est celui que le dépôt mobile documente lui-même + # (doc/SERVICES.md) : ERPLIBRE_MANIFEST_PATH. On le pointe sur un + # manifeste VIDE — « ces dépôts-là : aucun » — et le plugin + # l'annonce, « 0 repos ». Mesuré : dist passe de 123 019 à 336 + # fichiers, l'APK sort à 59 Mo et 2 472 entrées. + # + # Qui veut les dépôts pose la variable lui-même : elle est + # respectée. À retirer quand le projet mobile saura les empaqueter + # sous la limite du ZIP. + # Chaîné par « && » comme le reste : un « ; » ici laisserait la + # compilation web démarrer alors que « npm ci » vient d'échouer. + "printf '' " + '> "$HOME/.erplibre-empty-manifest.xml" && ' f'mstep "{t("web bundle (vite build)")}" ' - f"'cd {el_dir}/mobile/erplibre_home_mobile && npm run build' && " + f"'cd {el_dir}/mobile/erplibre_home_mobile && " + "ERPLIBRE_MANIFEST_PATH=" + '"${ERPLIBRE_MANIFEST_PATH:-$HOME/.erplibre-empty-manifest.xml}" ' + "npm run build' && " f'mstep "{t("native sync (capacitor)")}" ' f"'cd {el_dir}/mobile/erplibre_home_mobile && npx cap sync android' && " # UNE seule ABI, celle de la VM — qui est aussi celle de diff --git a/script/todo/todo_i18n.py b/script/todo/todo_i18n.py index 8abe4a7..5aeccfb 100644 --- a/script/todo/todo_i18n.py +++ b/script/todo/todo_i18n.py @@ -2289,6 +2289,10 @@ TRANSLATIONS = { "en": "no swap could be added; build may run short", }, "memory:": {"fr": "mémoire :", "en": "memory:"}, + "manifest repos not bundled (ZIP entry limit)": { + "fr": "dépôts du manifeste non empaquetés (limite d'entrées ZIP)", + "en": "manifest repos not bundled (ZIP entry limit)", + }, "MB RAM,": {"fr": "Mo de RAM,", "en": "MB RAM,"}, "MB swap, kernel OOM kills:": { "fr": "Mo de swap, tués par le noyau (OOM) :", diff --git a/test/test_qemu_desktop_tools.py b/test/test_qemu_desktop_tools.py index 4805dc3..69a677d 100644 --- a/test/test_qemu_desktop_tools.py +++ b/test/test_qemu_desktop_tools.py @@ -340,6 +340,33 @@ class TestMobileBuild(unittest.TestCase): res = self._run_steps(fail_on="gradle") self.assertNotEqual(0, res.returncode, res.stdout[-400:]) + def test_a_failed_step_stops_the_ones_after_it(self): + """La chaîne est en « && » d'un bout à l'autre. Un « ; » glissé au + milieu — celui qui écrivait le manifeste vide — laissait la compilation + web démarrer alors que « npm ci » venait d'échouer.""" + res = self._run_steps(fail_on="npm") + self.assertNotEqual(0, res.returncode) + self.assertNotIn("vite build", res.stdout) + self.assertNotIn("gradle", res.stdout) + + def test_the_manifest_repos_are_not_bundled(self): + """122 684 fichiers d'assets pour 337 qui sont l'application, et un APK + est un ZIP borné à 65 535 entrées. Le levier est celui que le dépôt + mobile documente : ERPLIBRE_MANIFEST_PATH, pointé sur un manifeste + vide. Mesuré : dist passe de 123 019 à 336 fichiers.""" + steps = self.todo._qemu_mobile_build_steps("/tmp/el") + self.assertIn("ERPLIBRE_MANIFEST_PATH=", steps) + self.assertIn("", steps) + # La variable posée par l'appelant gagne : qui veut les dépôts les a. + self.assertIn("${ERPLIBRE_MANIFEST_PATH:-", steps) + + def test_the_empty_manifest_is_written_before_the_bundle(self): + steps = self.todo._qemu_mobile_build_steps("/tmp/el") + self.assertLess( + steps.index("erplibre-empty-manifest.xml"), + steps.index("npm run build"), + ) + def test_a_missing_apk_fails_even_when_gradle_returns_zero(self): """L'APK est la preuve, pas le code de sortie de Gradle : une tâche peut rendre 0 sans rien produire."""