La CI de arcodange/kadans (Nuxt 3 + Vue 3 + Bun) a échoué au premier run : le runner Gitea Actions par défaut tourne en Node 18, or nuxi/nuxt importent styleText de node:util, une API ajoutée en Node 20 (v20.12). Le build casse avant même de démarrer (… does not provide an export named 'styleText'), alors que bun install a réussi — ce n'est pas un souci de Bun, c'est le Node de l'environnement.
Racine côté factory : les runners enregistrent deux labels (ubuntu-latest, ubuntu-latest-ca) qui pointent la même imagerunner-images:ubuntu-latest-ca, construite FROM gitea/runner-images:ubuntu-latest (Node 18) — cf. ansible/…/playbooks/03_cicd.yml (labels) + ansible/…/playbooks/ssl/ssl.yml (image + CA). Sans conteneur explicite, tout job (app ou factory) hérite de ce Node 18.
Le fix appliqué côté kadans — container: node:20-bookworm + npm i -g bun — marche (CI verte) mais c'est un contournement par-repo : toute future app Bun/Nuxt de l'org retombera dans le piège. Factory est le bon endroit pour capitaliser la leçon.
Ce que cette PR ajoute
doc/runbooks/new-web-app/06b-bun-nuxt-ci.md (nouvelle page) : le piège Node 18→20, la parade container: node:20-bookworm + Bun via npm, un ci.yml canonique à copier (repris de kadans, vérifié), les points de vigilance (Bun via npm, --frozen-lockfile, bookworm vs alpine, et le CA du homelab dont node:20-bookworm n'hérite pas), et les pistes infra.
06-ci-workflows.md : backlink bidirectionnel vers 6b + une phrase distinguant ci.yml (gates qualité) de vault.yaml/dockerimage.yaml.
README.md (index du runbook) : ligne 06b + bump Last Updated.
Aucun changement d'infra runner dans cette PR (voir alternatives) — c'est le minimum viable qui rend la parade découvrable pour la prochaine app.
Alternatives / pistes laissées à l'arbitrage
Documentées en fin de page 6b, car elles touchent la prod runner (rebuild d'image + re-run Ansible 03_cicd sur pi1/pi3, pas un simple merge) :
Bumper l'image runner (ssl.yml) vers une base gitea/runner-images en Node 20+. Rayon large : impacte tous les jobs, y compris iac.yaml/postgres.yaml de factory (runs-on: ubuntu-latest-ca) — à revalider.
Label node20 dédié : image runner-images:node20-ca (FROM node:20-bookworm + CA homelab) exposée via un label dans 03_cicd.yml. Opt-in (runs-on: node20), avec le CA (lève la limite TLS de la parade vanilla vers https://gitea.arcodange.lab). Plus sûr, mais une image de plus à maintenir.
Action réutilisable bun-nuxt-ci (sur le modèle de arcodange-org/vault-action) pour éviter le copier-coller du YAML, indépendamment du Node du runner.
Recommandation : garder la parade container: documentée comme contrat par défaut ; si tu veux retirer le contournement, la piste 2 (opt-in, CA-safe) est la moins risquée.
## Problème
La CI de [`arcodange/kadans`](https://gitea.arcodange.lab/arcodange/kadans) (Nuxt 3 + Vue 3 + Bun) a échoué au **premier run** : le runner Gitea Actions par défaut tourne en **Node 18**, or `nuxi`/`nuxt` importent **`styleText` de `node:util`**, une API ajoutée en **Node 20** (v20.12). Le build casse avant même de démarrer (`… does not provide an export named 'styleText'`), alors que `bun install` a réussi — ce n'est pas un souci de Bun, c'est le **Node** de l'environnement.
Racine côté factory : les runners enregistrent deux labels (`ubuntu-latest`, `ubuntu-latest-ca`) qui pointent **la même image** `runner-images:ubuntu-latest-ca`, construite `FROM gitea/runner-images:ubuntu-latest` (Node 18) — cf. [`ansible/…/playbooks/03_cicd.yml`](https://gitea.arcodange.lab/arcodange-org/factory/src/branch/main/ansible/arcodange/factory/playbooks/03_cicd.yml) (labels) + [`ansible/…/playbooks/ssl/ssl.yml`](https://gitea.arcodange.lab/arcodange-org/factory/src/branch/main/ansible/arcodange/factory/playbooks/ssl/ssl.yml) (image + CA). Sans conteneur explicite, **tout job** (app ou factory) hérite de ce Node 18.
Le fix appliqué côté kadans — `container: node:20-bookworm` + `npm i -g bun` — marche (CI verte) mais c'est un contournement **par-repo** : toute future app Bun/Nuxt de l'org retombera dans le piège. Factory est le bon endroit pour capitaliser la leçon.
## Ce que cette PR ajoute
- **`doc/runbooks/new-web-app/06b-bun-nuxt-ci.md`** (nouvelle page) : le piège Node 18→20, la parade `container: node:20-bookworm` + Bun via npm, un **`ci.yml` canonique à copier** (repris de kadans, vérifié), les points de vigilance (Bun via npm, `--frozen-lockfile`, `bookworm` vs `alpine`, et le **CA du homelab** dont `node:20-bookworm` n'hérite pas), et les pistes infra.
- **`06-ci-workflows.md`** : backlink bidirectionnel vers 6b + une phrase distinguant `ci.yml` (gates qualité) de `vault.yaml`/`dockerimage.yaml`.
- **`README.md`** (index du runbook) : ligne `06b` + bump `Last Updated`.
Aucun changement d'infra runner dans cette PR (voir alternatives) — c'est le **minimum viable** qui rend la parade découvrable pour la prochaine app.
## Alternatives / pistes laissées à l'arbitrage
Documentées en fin de page 6b, car elles touchent la **prod runner** (rebuild d'image + re-run Ansible `03_cicd` sur `pi1`/`pi3`, pas un simple merge) :
1. **Bumper l'image runner** (`ssl.yml`) vers une base `gitea/runner-images` en Node 20+. Rayon large : impacte **tous** les jobs, y compris `iac.yaml`/`postgres.yaml` de factory (`runs-on: ubuntu-latest-ca`) — à revalider.
2. **Label `node20` dédié** : image `runner-images:node20-ca` (`FROM node:20-bookworm` + CA homelab) exposée via un label dans `03_cicd.yml`. Opt-in (`runs-on: node20`), **avec** le CA (lève la limite TLS de la parade vanilla vers `https://gitea.arcodange.lab`). Plus sûr, mais une image de plus à maintenir.
3. **Action réutilisable `bun-nuxt-ci`** (sur le modèle de `arcodange-org/vault-action`) pour éviter le copier-coller du YAML, indépendamment du Node du runner.
Recommandation : garder la parade `container:` documentée comme **contrat par défaut** ; si tu veux retirer le contournement, la **piste 2** (opt-in, CA-safe) est la moins risquée.
Related : [ADR 03 — CI/CD Gitea Action + ArgoCD](../src/branch/main/doc/adr/03_cicd_gitea_action_argocd.md).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Nouvelle page runbook « CI des apps Bun/Nuxt » : le runner par défaut est en
Node 18, or nuxi/nuxt importent styleText de node:util (Node 20+) → la CI casse
au build. Parade tenue (validée sur arcodange/kadans) : container node:20-bookworm
+ Bun via npm. Inclut un ci.yml canonique à copier + les pistes infra runner.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Ajoute le backlink bidirectionnel vers 06b et une phrase dans le Summary
distinguant ci.yml (gates qualité) des workflows vault.yaml/dockerimage.yaml.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Ajoute la ligne 06b (CI des apps Bun/Nuxt) à l'index des étapes et bump
Last Updated, conformément à la règle « Comment éditer ce runbook ».
Co-Authored-By: Claude Opus 4.8 <[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.
Problème
La CI de
arcodange/kadans(Nuxt 3 + Vue 3 + Bun) a échoué au premier run : le runner Gitea Actions par défaut tourne en Node 18, ornuxi/nuxtimportentstyleTextdenode:util, une API ajoutée en Node 20 (v20.12). Le build casse avant même de démarrer (… does not provide an export named 'styleText'), alors quebun installa réussi — ce n'est pas un souci de Bun, c'est le Node de l'environnement.Racine côté factory : les runners enregistrent deux labels (
ubuntu-latest,ubuntu-latest-ca) qui pointent la même imagerunner-images:ubuntu-latest-ca, construiteFROM gitea/runner-images:ubuntu-latest(Node 18) — cf.ansible/…/playbooks/03_cicd.yml(labels) +ansible/…/playbooks/ssl/ssl.yml(image + CA). Sans conteneur explicite, tout job (app ou factory) hérite de ce Node 18.Le fix appliqué côté kadans —
container: node:20-bookworm+npm i -g bun— marche (CI verte) mais c'est un contournement par-repo : toute future app Bun/Nuxt de l'org retombera dans le piège. Factory est le bon endroit pour capitaliser la leçon.Ce que cette PR ajoute
doc/runbooks/new-web-app/06b-bun-nuxt-ci.md(nouvelle page) : le piège Node 18→20, la paradecontainer: node:20-bookworm+ Bun via npm, unci.ymlcanonique à copier (repris de kadans, vérifié), les points de vigilance (Bun via npm,--frozen-lockfile,bookwormvsalpine, et le CA du homelab dontnode:20-bookwormn'hérite pas), et les pistes infra.06-ci-workflows.md: backlink bidirectionnel vers 6b + une phrase distinguantci.yml(gates qualité) devault.yaml/dockerimage.yaml.README.md(index du runbook) : ligne06b+ bumpLast Updated.Aucun changement d'infra runner dans cette PR (voir alternatives) — c'est le minimum viable qui rend la parade découvrable pour la prochaine app.
Alternatives / pistes laissées à l'arbitrage
Documentées en fin de page 6b, car elles touchent la prod runner (rebuild d'image + re-run Ansible
03_cicdsurpi1/pi3, pas un simple merge) :ssl.yml) vers une basegitea/runner-imagesen Node 20+. Rayon large : impacte tous les jobs, y comprisiac.yaml/postgres.yamlde factory (runs-on: ubuntu-latest-ca) — à revalider.node20dédié : imagerunner-images:node20-ca(FROM node:20-bookworm+ CA homelab) exposée via un label dans03_cicd.yml. Opt-in (runs-on: node20), avec le CA (lève la limite TLS de la parade vanilla vershttps://gitea.arcodange.lab). Plus sûr, mais une image de plus à maintenir.bun-nuxt-ci(sur le modèle dearcodange-org/vault-action) pour éviter le copier-coller du YAML, indépendamment du Node du runner.Recommandation : garder la parade
container:documentée comme contrat par défaut ; si tu veux retirer le contournement, la piste 2 (opt-in, CA-safe) est la moins risquée.Related : ADR 03 — CI/CD Gitea Action + ArgoCD.
🤖 Generated with Claude Code