fix(ci_base_image) — l'image livrait Node 18 : deux défauts que seule sa CONSTRUCTION a montrés
J'avais écrit dans cette PR « je n'ai pas pu construire l'image, sa base vit
derrière le certificat interne ». C'était une SUPPOSITION NON TESTÉE, et elle est
fausse : `docker pull gitea.arcodange.lab/…/runner-images:ubuntu-latest-ca` passe
sans rien configurer. En la construisant vraiment, deux défauts sont sortis — et
aucun n'était visible à la lecture du Dockerfile.
1. `runner-images:ubuntu-latest-ca` LIVRE NODE 18 (v18.20.8). Or `nuxi` importe
`node:util.styleText`, absent de Node 18 : c'est la raison d'être du
`container: node:20-bookworm` de la CI de kadans, que son CLAUDE.md interdit
de retirer. Sans correctif, basculer la CI sur cette image cassait `nuxt build`
sur un message parlant d'un import introuvable — jamais d'une version de Node.
→ Node 20 installé depuis NodeSource.
2. ET INSTALLER NE SUFFISAIT PAS. Après l'installation, `node --version` rendait
TOUJOURS v18.20.8 : l'image de base précuit un node pour le toolcache d'act et
le met EN TÊTE du PATH.
which node → /opt/acttoolcache/node/18.20.8/arm64/bin/node
/usr/bin/node --version → v20.20.2 ← le bon, mais il PERD
→ l'entrée 18 du toolcache est retirée ; la résolution retombe sur
/usr/bin/node. ⚠ Conséquence assumée : `actions/setup-node` ne trouvera plus
de Node 18 préinstallé — aucun workflow de kadans ne l'utilise, et l'image
n'est servie qu'aux jobs qui DEMANDENT le label.
Le Dockerfile porte désormais une ASSERTION DE BUILD
(`node --version | grep -q "^v${NODE_MAJOR}\."`) : l'image ne peut plus se
construire si la résolution redevient mauvaise. Et le rôle vérifie la version au
déploiement (`failed_when`), au lieu de la supposer.
MESURES RÉELLES (construite en linux/arm64, l'architecture des runners) :
TOTAL 4,58 Go
├─ playwright install chromium 1,01 Go
├─ playwright install-deps 405 Mo
├─ Node 20 (NodeSource) 183 Mo
└─ bun 179 Mo
Vérifié dans l'image : which node → /usr/bin/node v20.20.2 · bun 1.3.14 ·
chromium-1228 + headless-shell + ffmpeg · /etc/ci-base.versions cohérent.
⚠ Ce que ces chiffres tranchent : le découpage en RUN séparés N'A PAS suffi à
rendre l'image poussable — 1,01 Go pour la plus grosse couche, soit ~4× les
261 Mo que le registre accepte (runner-images:ubuntu-latest-ca). Le build LOCAL
n'est donc pas une préférence, c'est la seule voie. Mesuré, plus supposé.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
@@ -31,6 +31,15 @@ ci_base_image_tag: latest
|
||||
ci_base_image_bun_version: '1.3.14'
|
||||
ci_base_image_playwright_version: '1.61.1'
|
||||
|
||||
# ⚠ NODE 20 EST OBLIGATOIRE, ET CE N'EST PAS UN CONFORT.
|
||||
# `runner-images:ubuntu-latest-ca` livre Node **18** (v18.20.8, constaté en
|
||||
# lançant l'image). Or `nuxi` importe `node:util.styleText`, absent de Node 18 :
|
||||
# c'est la raison d'être du `container: node:20-bookworm` que portait la CI de
|
||||
# kadans, et que son CLAUDE.md interdit de retirer. Sans cette surcharge, tout
|
||||
# job Nuxt basculé sur cette image casse au premier build, sur un message qui
|
||||
# parle d'un import introuvable et jamais d'une version de Node.
|
||||
ci_base_image_node_major: 20
|
||||
|
||||
# Épinglage par conteneur factice — remède décrit par
|
||||
# docs/adr/20260407-docker-storage-gitea-runner.md §1, jusqu'ici resté à l'état
|
||||
# de proposition (system_docker.yml n'applique que le data-root et les log-opts).
|
||||
|
||||
@@ -42,7 +42,43 @@ ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
|
||||
# la couche redeviendrait impossible à transporter.
|
||||
# ══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
# 1. Bun (~274 Mo)
|
||||
# 0. NODE 20, ET C'EST OBLIGATOIRE — pas une préférence.
|
||||
#
|
||||
# ⚠ `runner-images:ubuntu-latest-ca` livre **Node 18** (v18.20.8, vérifié en le
|
||||
# lançant). Or `nuxi` importe `node:util.styleText`, ABSENT de Node 18 : c'est la
|
||||
# raison d'être du `container: node:20-bookworm` que la CI de kadans portait, et
|
||||
# que son `CLAUDE.md` interdit explicitement de retirer.
|
||||
#
|
||||
# Sans cette couche, une CI qui bascule sur cette image casse au premier `nuxt
|
||||
# build` — et le message parle d'un import introuvable, pas d'une version de Node.
|
||||
# Le défaut a été trouvé en CONSTRUISANT l'image puis en lançant `node --version`
|
||||
# dedans ; aucune lecture du Dockerfile ne l'aurait montré.
|
||||
# ⚠⚠ ET INSTALLER NE SUFFIT PAS — il faut aussi que `node` RÉSOLVE vers le bon.
|
||||
# Constaté en lançant l'image : après l'installation de Node 20 par apt,
|
||||
# `node --version` rendait toujours **v18.20.8**, parce que l'image de base
|
||||
# précuit un node pour le toolcache d'act et le met EN TÊTE du PATH :
|
||||
#
|
||||
# which node → /opt/acttoolcache/node/18.20.8/arm64/bin/node
|
||||
# PATH → /opt/acttoolcache/node/18.20.8/arm64/bin:/usr/local/sbin:/usr/bin:…
|
||||
# /usr/bin/node --version → v20.20.2 ← le bon, mais il PERD
|
||||
#
|
||||
# On retire donc l'entrée 18 du toolcache : le segment de PATH devient inexistant
|
||||
# (inoffensif) et la résolution retombe sur /usr/bin/node, en 20.
|
||||
# ⚠ Conséquence assumée : `actions/setup-node` ne trouvera plus de Node 18
|
||||
# préinstallé dans cette image. Aucun workflow de kadans ne l'utilise, et l'image
|
||||
# n'est servie qu'aux jobs qui DEMANDENT le label `ci-node-playwright`.
|
||||
ARG NODE_MAJOR=20
|
||||
RUN curl -fsSL "https://deb.nodesource.com/setup_${NODE_MAJOR}.x" -o /tmp/nodesource.sh \
|
||||
&& bash /tmp/nodesource.sh \
|
||||
&& apt-get install -y --no-install-recommends nodejs \
|
||||
&& rm -f /tmp/nodesource.sh \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& rm -rf /opt/acttoolcache/node \
|
||||
&& echo "node résolu : $(which node) $(node --version)" \
|
||||
&& node --version | grep -q "^v${NODE_MAJOR}\."
|
||||
|
||||
# 1. Bun (~180 Mo) — installé APRÈS Node 20, pour que son npm global soit celui
|
||||
# de Node 20 et non celui de Node 18.
|
||||
RUN npm install -g "bun@${BUN_VERSION}" \
|
||||
&& npm cache clean --force
|
||||
|
||||
@@ -59,7 +95,7 @@ RUN npx --yes "playwright@${PLAYWRIGHT_VERSION}" install chromium
|
||||
# la confronte à son `bun.lock` : une dérive de version doit échouer FORT, avec sa
|
||||
# cause, plutôt que de se manifester par un « Executable doesn't exist » à
|
||||
# vingt minutes de là.
|
||||
RUN printf 'bun=%s\nplaywright=%s\n' \
|
||||
"$(bun --version)" "${PLAYWRIGHT_VERSION}" \
|
||||
RUN printf 'node=%s\nbun=%s\nplaywright=%s\n' \
|
||||
"$(node --version)" "$(bun --version)" "${PLAYWRIGHT_VERSION}" \
|
||||
> /etc/ci-base.versions \
|
||||
&& cat /etc/ci-base.versions
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
rebuild: '{{ "always" if ci_base_image_force_rebuild else "never" }}'
|
||||
args:
|
||||
CI_BASE_FROM: '{{ ci_base_image_from }}'
|
||||
NODE_MAJOR: '{{ ci_base_image_node_major }}'
|
||||
BUN_VERSION: '{{ ci_base_image_bun_version }}'
|
||||
PLAYWRIGHT_VERSION: '{{ ci_base_image_playwright_version }}'
|
||||
register: ci_base_image_build
|
||||
@@ -40,13 +41,19 @@
|
||||
# Contrôle de sortie : on VÉRIFIE que l'image répond, plutôt que de supposer que
|
||||
# le build a suffi. Une image construite mais dont `bun` n'est pas dans le PATH
|
||||
# passerait le build et casserait tous les jobs.
|
||||
- name: Vérifier que l'image livre bien bun et chromium
|
||||
- name: Vérifier que l'image livre bien Node {{ ci_base_image_node_major }}, bun et chromium
|
||||
ansible.builtin.command:
|
||||
cmd: >-
|
||||
docker run --rm {{ ci_base_image_name }}:{{ ci_base_image_tag }}
|
||||
sh -c "bun --version && cat /etc/ci-base.versions"
|
||||
sh -c "node --version && bun --version && ls /ms-playwright && cat /etc/ci-base.versions"
|
||||
register: ci_base_image_check
|
||||
changed_when: false
|
||||
# ⚠ La version de Node est VÉRIFIÉE, pas supposée : l'image de base en livre
|
||||
# une trop ancienne (18), et une régression silencieuse ici casserait tout job
|
||||
# Nuxt sur un message qui ne nomme pas la cause.
|
||||
failed_when: >-
|
||||
ci_base_image_check.rc != 0
|
||||
or ('v' ~ ci_base_image_node_major ~ '.') not in ci_base_image_check.stdout
|
||||
|
||||
- name: Ce que l'image contient réellement
|
||||
ansible.builtin.debug:
|
||||
|
||||
Reference in New Issue
Block a user