[FIX] script todo: ne plus empaqueter les dépôts du manifeste dans l'APK

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
This commit is contained in:
Mathieu Benoit 2026-08-19 05:57:22 -04:00
parent 9e69cfa49c
commit aa94e460ec
6 changed files with 104 additions and 17 deletions

View file

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

View file

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

View file

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

View file

@ -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 '<manifest></manifest>' "
'> "$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

View file

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

View file

@ -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("<manifest></manifest>", 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."""