Corrige un défaut de factory#48 trouvé au premier passage réel du playbook, et ajoute la reconstruction conditionnelle.
Le défaut
ansible-playbook 03_cicd.yml est mort sur les deux hôtes :
"/Users/…/collections/…/roles/ci_base_image/files/" is not an existing directory
community.docker.docker_image_build s'exécute sur la cible : son path: désigne 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é : --syntax-check passait, le YAML était valide. Seule l'exécution le dit.
✅L'échec est arrivé avant les tâches qui déploient les runners. Les deux sont restés Up 6 days, aucune CI cassée. Le seul effet fut un jeton d'API Gitea créé par le rôle gitea_token — son comportement normal à chaque passage. C'est la bonne propriété pour un playbook qui touche la CI de toute la forge.
Le correctif
Le contexte de build est déposé sur la machine (/tmp/ci-base-image, variable ci_base_image_contexte) avant le build.
Et la reconstruction devient conditionnelle
rebuild: 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 (ci_base_image_dockerfile is changed).
Ajouter une bibliothèque à l'image devient donc effectif sans avoir à penser à un drapeau. ci_base_image_force_rebuild reste utile pour ce 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.
✅ Vérifié : le playbook passe, et l'image est là
pi1 et pi3 : ok=17 changed=8 failed=0.
pi1
pi3
image ci-node-playwright
3,34 Go
3,34 Go (construite par ce passage)
Node dans l'image
v20.20.2
v20.20.2
bun / chromium / headless-shell / ffmpeg
✅
✅
conteneur d'épinglage
Created
Created
runner après recréation
Up
Up
La tâche de vérification relit les versions dans l'image sur chaque hôte (docker run … node --version && bun --version && ls /ms-playwright && cat /etc/ci-base.versions) et failed_when refuse une version de Node qui ne serait pas celle attendue — elle ne suppose rien.
Ce qui reste à éprouver
Que la CI de kadans consomme réellement l'image via le label ci-node-playwright. C'est l'objet de kadans#227, et ça se teste par un run déclenché sur sa branche — je le fais dans la foulée.
Corrige un défaut de `factory#48` trouvé **au premier passage réel** du playbook, et ajoute la reconstruction conditionnelle.
## Le défaut
`ansible-playbook 03_cicd.yml` est mort sur les **deux** hôtes :
```
"/Users/…/collections/…/roles/ci_base_image/files/" is not an existing directory
```
`community.docker.docker_image_build` s'exécute **sur la cible** : son `path:` désigne 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é** : `--syntax-check` passait, le YAML était valide. Seule l'exécution le dit.
> ✅ **L'échec est arrivé avant les tâches qui déploient les runners.** Les deux sont restés `Up 6 days`, aucune CI cassée. Le seul effet fut un jeton d'API Gitea créé par le rôle `gitea_token` — son comportement normal à chaque passage. C'est la bonne propriété pour un playbook qui touche la CI de toute la forge.
## Le correctif
Le contexte de build est déposé sur la machine (`/tmp/ci-base-image`, variable `ci_base_image_contexte`) avant le build.
## Et la reconstruction devient conditionnelle
`rebuild: 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** (`ci_base_image_dockerfile is changed`).
Ajouter une bibliothèque à l'image devient donc effectif **sans avoir à penser à un drapeau**. `ci_base_image_force_rebuild` reste utile pour ce 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.
## ✅ Vérifié : le playbook passe, et l'image est là
`pi1` et `pi3` : `ok=17 changed=8 failed=0`.
| | pi1 | pi3 |
|---|---|---|
| image `ci-node-playwright` | 3,34 Go | **3,34 Go** (construite par ce passage) |
| Node **dans** l'image | **v20.20.2** | **v20.20.2** |
| bun / chromium / headless-shell / ffmpeg | ✅ | ✅ |
| conteneur d'épinglage | `Created` | `Created` |
| runner après recréation | `Up` | `Up` |
La tâche de vérification relit les versions **dans** l'image sur chaque hôte (`docker run … node --version && bun --version && ls /ms-playwright && cat /etc/ci-base.versions`) et `failed_when` refuse une version de Node qui ne serait pas celle attendue — elle ne suppose rien.
## Ce qui reste à éprouver
Que la CI de `kadans` consomme réellement l'image via le label `ci-node-playwright`. C'est l'objet de [kadans#227](https://gitea.arcodange.lab/arcodange/kadans/pulls/227), et ça se teste par un run déclenché sur sa branche — je le fais dans la foulée.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
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) <[email protected]>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Corrige un défaut de
factory#48trouvé au premier passage réel du playbook, et ajoute la reconstruction conditionnelle.Le défaut
ansible-playbook 03_cicd.ymlest mort sur les deux hôtes :community.docker.docker_image_builds'exécute sur la cible : sonpath:désigne 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é :--syntax-checkpassait, le YAML était valide. Seule l'exécution le dit.Le correctif
Le contexte de build est déposé sur la machine (
/tmp/ci-base-image, variableci_base_image_contexte) avant le build.Et la reconstruction devient conditionnelle
rebuild: neveren régime normal — le playbook ne rebâtit pas 3,3 Go à chaque passage — maisalwaysdès que le Dockerfile a changé sur la machine (ci_base_image_dockerfile is changed).Ajouter une bibliothèque à l'image devient donc effectif sans avoir à penser à un drapeau.
ci_base_image_force_rebuildreste utile pour ce que le Dockerfile ne montre pas — une montée debun.lockcôtékadans, par exemple, qui change les versions attendues sans changer le fichier.✅ Vérifié : le playbook passe, et l'image est là
pi1etpi3:ok=17 changed=8 failed=0.ci-node-playwrightCreatedCreatedUpUpLa tâche de vérification relit les versions dans l'image sur chaque hôte (
docker run … node --version && bun --version && ls /ms-playwright && cat /etc/ci-base.versions) etfailed_whenrefuse une version de Node qui ne serait pas celle attendue — elle ne suppose rien.Ce qui reste à éprouver
Que la CI de
kadansconsomme réellement l'image via le labelci-node-playwright. C'est l'objet de kadans#227, et ça se teste par un run déclenché sur sa branche — je le fais dans la foulée.🤖 Generated with Claude Code
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) <[email protected]>