From ba791ed05581e9341c5fe35988d8d04d88e9b594 Mon Sep 17 00:00:00 2001 From: CI Bot Date: Wed, 29 Jul 2026 23:41:32 +0200 Subject: [PATCH] =?UTF-8?q?fix(ci=5Fbase=5Fimage)=20=E2=80=94=20le=20conte?= =?UTF-8?q?xte=20de=20build=20doit=20=C3=AAtre=20SUR=20la=20machine,=20pas?= =?UTF-8?q?=20sur=20le=20contr=C3=B4leur?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le playbook 03_cicd est mort sur les deux hôtes : "/Users/…/roles/ci_base_image/files/" is not an existing directory `docker_image_build` s'exécute SUR LA CIBLE : son `path:` est un chemin de la cible. Je passais `{{ role_path }}/files/`, un chemin du CONTRÔLEUR. Le motif venait du rôle `playwright`, qui l'emploie LÉGITIMEMENT parce qu'il construit en local. Recopié pour un build distant, il ne pouvait pas marcher — et aucune relecture ne l'aurait montré, seule l'exécution le dit. ⚠ L'échec est arrivé AVANT les tâches qui déploient le runner : les deux runners sont restés `Up 6 days`, rien n'a été cassé. Le seul effet fut un jeton d'API Gitea créé par le rôle gitea_token, son comportement normal. Le contexte est désormais déposé sur la machine (`/tmp/ci-base-image`), et la RECONSTRUCTION DEVIENT CONDITIONNELLE : `never` en régime normal — le playbook ne rebâtit pas 3,3 Go à chaque passage — mais `always` dès que le Dockerfile a CHANGÉ sur la machine. Ajouter une bibliothèque devient donc effectif sans avoir à penser à un drapeau. Co-Authored-By: Claude Opus 5 (1M context) --- .../roles/ci_base_image/defaults/main.yml | 12 +++++- .../roles/ci_base_image/tasks/main.yml | 37 ++++++++++++++++++- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/ansible/arcodange/factory/roles/ci_base_image/defaults/main.yml b/ansible/arcodange/factory/roles/ci_base_image/defaults/main.yml index e242e9a..9f88843 100644 --- a/ansible/arcodange/factory/roles/ci_base_image/defaults/main.yml +++ b/ansible/arcodange/factory/roles/ci_base_image/defaults/main.yml @@ -48,5 +48,15 @@ ci_base_image_node_major: 20 # images de runner elles-mêmes. ci_base_image_pin: true -# Reconstruire même si l'image existe déjà (utile après un changement de version). +# Où le contexte de build est déposé SUR LA MACHINE CIBLE. `docker_image_build` +# s'exécute sur la cible : son `path:` est un chemin de la cible, jamais du +# contrôleur. (Première version : `{{ role_path }}/files/` → le playbook mourait +# sur « is not an existing directory », sur les deux hôtes.) +ci_base_image_contexte: /tmp/ci-base-image + +# Reconstruire même si l'image existe déjà. ⚠ Inutile pour un simple changement +# du Dockerfile : le rôle le détecte et reconstruit tout seul (voir tasks/). +# Ce drapeau sert aux cas que le Dockerfile ne montre pas — une montée de +# `bun.lock` côté kadans, par exemple, qui change les VERSIONS attendues sans +# changer le fichier. ci_base_image_force_rebuild: false diff --git a/ansible/arcodange/factory/roles/ci_base_image/tasks/main.yml b/ansible/arcodange/factory/roles/ci_base_image/tasks/main.yml index 5ac76f2..f1ab121 100644 --- a/ansible/arcodange/factory/roles/ci_base_image/tasks/main.yml +++ b/ansible/arcodange/factory/roles/ci_base_image/tasks/main.yml @@ -6,12 +6,45 @@ # atterrit sur une machine sans l'image échouerait AVANT sa première étape — # `runs-on`/`container:` est résolu par le runner, pas par le workflow. +# ══════════════════════════════════════════════════════════════════════════ +# ⚠ LE CONTEXTE DE BUILD DOIT ÊTRE SUR LA MACHINE, PAS SUR LE CONTRÔLEUR. +# +# `docker_image_build` s'exécute SUR LA CIBLE : son `path:` est un chemin de la +# cible. La première version passait `{{ role_path }}/files/` — un chemin du +# CONTRÔLEUR — et le playbook mourait sur les deux hôtes : +# +# "/Users/…/roles/ci_base_image/files/" is not an existing directory +# +# Le motif venait du rôle `playwright`, qui l'utilise LÉGITIMEMENT parce qu'il +# construit en local ; recopié tel quel pour un build distant, il ne peut pas +# marcher. On copie donc le contexte d'abord. +# ══════════════════════════════════════════════════════════════════════════ +- name: Créer le répertoire de contexte de build sur la machine + ansible.builtin.file: + path: '{{ ci_base_image_contexte }}' + state: directory + mode: '0755' + +- name: Déposer le Dockerfile sur la machine + ansible.builtin.copy: + src: Dockerfile + dest: '{{ ci_base_image_contexte }}/Dockerfile' + mode: '0644' + register: ci_base_image_dockerfile + - name: Construire {{ ci_base_image_name }}:{{ ci_base_image_tag }} community.docker.docker_image_build: name: '{{ ci_base_image_name }}' tag: '{{ ci_base_image_tag }}' - path: '{{ role_path }}/files/' - rebuild: '{{ "always" if ci_base_image_force_rebuild else "never" }}' + path: '{{ ci_base_image_contexte }}' + # RECONSTRUCTION CONDITIONNELLE : `never` en régime normal (le playbook ne + # rebâtit pas 3,3 Go à chaque passage), mais `always` dès que le Dockerfile + # a CHANGÉ sur la machine — c'est ce qui rend l'ajout d'une bibliothèque + # effectif sans avoir à penser à un drapeau. + rebuild: >- + {{ "always" + if (ci_base_image_force_rebuild or ci_base_image_dockerfile is changed) + else "never" }} args: CI_BASE_FROM: '{{ ci_base_image_from }}' NODE_MAJOR: '{{ ci_base_image_node_major }}'