Skip to content

Bloc 97 — 🐛 CI : « Verify Docker Compose health » rouge sur main (mauvaise image) - #122

Merged
magicgg91 merged 1 commit into
devfrom
claude/bloc-97-ci-compose-image
Sep 14, 2026
Merged

magicgg91 merged 1 commit into
devfrom
claude/bloc-97-ci-compose-image

Conversation

@magicgg91

Copy link
Copy Markdown
Owner

Cause, confirmée par les logs

L'erreur exacte, dans les logs de l'étape (run 34835198084) :

Container ml-helper-app-1  Error response from daemon:
No such image: ghcr.io/magicgg91/ml-helper:dev

Des trois pistes du brief, c'est la première : le conteneur n'a jamais démarré. Ni healthcheck en échec, ni timeout. Trois faits le confirment :

  • l'étape a duré moins d'une seconde (10:59:1110:59:11), loin des 180 s de --wait-timeout ;
  • « Show Docker Compose logs on failure » n'a rien affiché — il n'y avait aucun conteneur dont lire les logs ;
  • docker compose down --volumes n'a retiré qu'un réseau, aucun conteneur.

Le mécanisme. Le job construit et charge ghcr.io/magicgg91/ml-helper:latest sur main, :dev ailleurs. Mais l'étape Compose ne passait pas ML_HELPER_IMAGE : Compose retombait donc sur son propre défaut, :dev (docker-compose.yml:3), avec --pull never qui interdit d'aller le chercher. Sur dev les deux chaînes coïncidaient — par coïncidence, pas par construction. Sur main elles divergent, et l'image demandée n'avait jamais existé sur le runner.

Pourquoi jamais vu avant. Ton intuition était la bonne, et l'historique la confirme : l'étape Compose et la variable ML_HELPER_IMAGE sont arrivées ensemble le 2026-09-02 (ccc1481, PR #86), et le dernier push sur main avant celui-ci datait du 2026-08-31. Ce run est la toute première exécution de cette étape sur main.

Ce n'est pas un secret ou une variable manquante. L'étape fait touch .env, toutes les variables du compose ont un défaut :-, le docker/login-action a réussi, et l'échec précède de toute façon toute lecture d'environnement.

Reproduction locale — à l'identique

Avec uniquement :latest présent en local (ce que fait le job sur main), la commande exacte de l'étape :

 Container ml-helper-app-1  Error response from daemon: No such image: ghcr.io/magicgg91/ml-helper:dev
>>> exit code: 1

Même message, au caractère près. En passant ML_HELPER_IMAGE, l'erreur disparaît (0 occurrence).

Limite honnête : la politique réseau de cet environnement bloque le pull des images de base Docker Hub (403 sur production.cloudfront.docker.com), je n'ai donc pas pu construire l'image réelle et aller jusqu'à healthy — j'ai reproduit la résolution d'image, qui est exactement là où ça cassait. Le trajet complet jusqu'à healthy sera confirmé par le prochain push sur main.

Correctif

Nommer l'image une seule fois, au niveau du job, sous le nom que Compose lit lui-même :

    env:
      ML_HELPER_IMAGE: "ghcr.io/magicgg91/ml-helper:${{ github.ref_name == 'main' && 'latest' || 'dev' }}"

Les quatre étapes (build, vérification de démarrage, Compose, push) s'y réfèrent désormais. Compose reçoit l'image que le job vient de construire, sur les deux branches, et les deux fichiers ne peuvent plus diverger. Le défaut :dev de docker-compose.yml reste inchangé : il est documenté dans README.md:28 comme le canal roulant, et le changer modifierait le comportement de ton déploiement.

En prime, une ligne : la description du statut GitHub publié en cas d'échec accusait la santé d'un conteneur qui n'avait jamais démarré. C'est ce qui a rendu ce diagnostic nécessaire — elle couvre maintenant les deux cas.

Test

src/foundation.test.ts (qui teste déjà Compose/Dockerfile/healthcheck en texte) épingle le lien entre les deux fichiers : Compose lit bien ${ML_HELPER_IMAGE:-}, le workflow le définit, et le tag n'est écrit qu'une seule fois hors commentaires.

Contre-vérifié dans les deux sens : retirer la variable (l'état d'avant) rougit 2 tests ; remettre un tag en dur dans une étape en rougit 1.

Validation

  • pnpm lint : propre
  • pnpm test : 1275 tests verts (+2)
  • YAML du workflow : parsé, jobs.image.env bien lu
  • Build et e2e non relancés : aucun code applicatif n'est touché (un fichier de workflow, un fichier de test)
  • ci.yml était déjà hors format Prettier avant ce changement (vérifié sur la version HEAD) — je ne l'ai pas reformaté, la dérive n'est pas de mon fait

⚠️ À savoir pour la suite

Le job image ne tourne que sur push (if: github.event_name == 'push'), donc la CI de cette PR n'exercera pas le correctif — seul le job test s'exécutera. Il sera exercé au push sur dev après merge (tag :dev, le chemin qui marchait déjà), et réellement validé au prochain merge devmain.

Et main reste rouge jusqu'à ce prochain merge : le job image ne se relancera sur main qu'au prochain push.

🤖 Generated with Claude Code

https://claude.ai/code/session_01HJgsDSfsCbbn8cochFGwe2


Generated by Claude Code

…nstruire

Diagnostic (run 34835198084, commit 065ed7a sur main). L'erreur exacte,
dans les logs de l'étape :

    Container ml-helper-app-1  Error response from daemon:
    No such image: ghcr.io/magicgg91/ml-helper:dev

Le conteneur n'a donc jamais démarré : ce n'est ni un healthcheck qui
échoue, ni un timeout. L'étape a duré moins d'une seconde (10:59:11 →
10:59:11), loin des 180 s de `--wait-timeout`, et « Show Docker Compose
logs on failure » n'a rien affiché — il n'y avait aucun conteneur.

Cause : le job construit et charge `:latest` sur main, `:dev` ailleurs,
mais l'étape Compose ne passait pas `ML_HELPER_IMAGE`. Compose retombait
donc sur son propre défaut, `:dev` (docker-compose.yml), avec
`--pull never`. Sur dev les deux chaînes coïncidaient par hasard ; sur
main elles divergent, et l'image demandée n'avait jamais existé sur le
runner.

Jamais vu avant parce que ce chemin n'avait jamais été emprunté :
l'étape Compose et la variable ML_HELPER_IMAGE sont arrivées ensemble le
2026-09-02 (ccc1481), et le dernier push sur main avant celui-ci datait
du 2026-08-31. Ce run est la première exécution de cette étape sur main.

Aucun secret ni variable d'environnement ne manque : l'étape fait
`touch .env`, toutes les variables du compose ont un défaut `:-`, le
login ghcr a réussi, et l'échec précède de toute façon toute lecture
d'environnement.

Correctif : nommer l'image une seule fois, au niveau du job, sous le nom
que Compose lit lui-même (ML_HELPER_IMAGE). Les quatre étapes (build,
vérification de démarrage, Compose, push) s'y réfèrent, donc les deux
fichiers ne peuvent plus diverger. Le défaut `:dev` de
docker-compose.yml reste inchangé — il est documenté dans README.md.

La description du statut GitHub publié en cas d'échec accusait la santé
du conteneur pour un conteneur qui n'avait jamais démarré ; elle couvre
maintenant les deux cas.

Reproduction locale, à l'identique : avec seulement `:latest` en local
(ce que fait le job sur main), `docker compose up -d --pull never` sort
le même « No such image: ghcr.io/magicgg91/ml-helper:dev » ; en passant
ML_HELPER_IMAGE, l'erreur disparaît. L'image réelle n'a pas pu être
construite ici (la politique réseau de l'environnement bloque le pull
des images de base Docker Hub), donc le passage jusqu'à « healthy » reste
à confirmer par le prochain push sur main.

Test : src/foundation.test.ts épingle le lien entre les deux fichiers —
Compose lit bien ${ML_HELPER_IMAGE:-}, le workflow le définit, et le tag
n'est écrit qu'une fois hors commentaires. Contre-vérifié : retirer la
variable rougit 2 tests, remettre un tag en dur dans une étape en rougit 1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJgsDSfsCbbn8cochFGwe2
@magicgg91
magicgg91 merged commit 94b03c3 into dev Sep 14, 2026
2 checks passed
@magicgg91
magicgg91 deleted the claude/bloc-97-ci-compose-image branch September 14, 2026 12:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants