From a2d09246564e8acf3ebb20ae9b2495876e0486b9 Mon Sep 17 00:00:00 2001 From: Gabriel Radureau Date: Mon, 7 Sep 2026 18:02:51 +0200 Subject: [PATCH] La publication du chart n'atteignait pas le registre, et ne pouvait pas le dire MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `main` est rouge depuis la fusion de #39 : `Application charts prometheus`, `curl` code 6, « couldn't resolve host ». Le repli DNS ajouté par cette PR-là avait été posé sur la DESCENTE des dépendances seulement ; l'étape de PUBLICATION était restée sur le nom d'origine. Un remède qui vit à deux endroits ne se propage pas par la vigilance — le commentaire le dit désormais à l'endroit où quelqu'un ajoutera le troisième appel. Et en le corrigeant, un second défaut, plus grave parce qu'il est muet : `curl` rend 0 sur un 401 comme sur un 409. L'étape passait au VERT en ne publiant rien. Mesuré le 2026-09-07 : le registre interne ne contenait que `minio 0.2.0` et `tool 0.1.0` — DEUX charts sur DIX — sans que rien n'ait jamais rougi. On relève donc le code HTTP et on en décide ; le code de sortie de `curl`, lui, ne parle que du transport. 409 est ACCEPTÉ et nommé : republier une version inchangée est le cas normal d'un lot qui ne touche pas au `version:` du chart, pas une faute. Éprouvé par sabotage, faux `curl` piloté, vrai shell du runner (`bash -e -o pipefail`), les deux côtés mesurés : cas AVANT APRÈS nom KO, repli KO exit 6 exit 1 « le registre est injoignable » nom KO, repli OK — exit 0 publié via la passerelle registre REFUSE (401) exit 0 exit 1 « publication REFUSÉE » déjà publié (409) exit 0 exit 0 « déjà présent, rien à republier » tout va bien (201) exit 0 exit 0 ⚠ Le jeton part par le repli, alors que la descente est anonyme. Ce n'est pas une exposition neuve : `actions/checkout` pose déjà son `extraheader` porteur du jeton de forge sur cette même URL de passerelle, à chaque job. ⚠ Trois fois de suite, mon banc a rendu un verdict faux avant de rendre le vrai : trace `set -x` prise pour de la sortie, variables qui n'atteignaient pas le script, puis `IFS` fuyant d'un `read` sous zsh et collant les affectations en une seule. Aucun verdict n'a été tiré sans avoir vérifié que le décor était posé — le banc l'imprime. Co-Authored-By: Claude Opus 5 --- .gitea/workflows/helmcharts.yaml | 45 +++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/.gitea/workflows/helmcharts.yaml b/.gitea/workflows/helmcharts.yaml index 03d3ec5..f4eb018 100644 --- a/.gitea/workflows/helmcharts.yaml +++ b/.gitea/workflows/helmcharts.yaml @@ -285,7 +285,50 @@ jobs: chart_package=${chart}-${chart_version}.tgz # helm package ${chart} tar -X ${chart}/.helmignore -czf ${chart_package} ${chart} - curl --user ${{ github.actor }}:${{ secrets.PACKAGES_TOKEN }} -X POST --upload-file ./${chart_package} https://gitea.arcodange.lab/api/packages/${{ github.repository_owner }}/helm/api/charts + + # ⚠⚠ LE MÊME REPLI QUE POUR LA DESCENTE DES DÉPENDANCES, ET C'EST + # POURQUOI CE COMMENTAIRE EXISTE. Le correctif du 2026-09-07 n'avait + # posé le repli QUE sur `helm_install_dependencies` ; celui-ci est + # resté sur le nom d'origine, et `main` est devenu rouge dès la + # fusion suivante — `curl` code 6, « couldn't resolve host ». + # **Un remède qui vit à DEUX endroits ne se propage pas par la + # vigilance.** Si un troisième appel au registre apparaît un jour, il + # a besoin de ces trois lignes lui aussi. + FORGE_INTERNE='https://gitea.arcodange.lab' + registre="${FORGE_INTERNE}/api/packages/${{ github.repository_owner }}/helm" + if ! curl -sf -o /dev/null -m 15 "${registre}/index.yaml"; then + repli="${registre/$FORGE_INTERNE/${GITHUB_SERVER_URL:-$FORGE_INTERNE}}" + if [[ "$repli" != "$registre" ]] && curl -sf -o /dev/null -m 15 "${repli}/index.yaml"; then + echo " ⚠ ${registre} injoignable depuis ce runner — repli sur ${repli}" + registre="$repli" + fi + fi + + # ⚠ ICI LE JETON PART, alors que la descente est anonyme. Le repli est + # `http://192.168.65.254:43000` — la passerelle Docker de l'hôte, en + # clair. Ce n'est pas une exposition NEUVE : `actions/checkout` pose + # déjà son `http..extraheader` porteur du jeton de forge à + # chaque job. Même chemin, même machine, même classe de risque. + + # ⚠⚠ ET L'APPEL DOIT POUVOIR ÉCHOUER. `curl` rend 0 sur un 401 comme + # sur un 409 : l'étape passait au vert en ne publiant rien. On relève + # donc le CODE HTTP (`-w`) et on en décide — le code de sortie de + # `curl`, lui, ne parle que du transport. Mesuré le 2026-09-07 : le + # registre ne contenait que `minio 0.2.0` et `tool 0.1.0`, deux + # charts sur dix, sans que rien n'ait jamais rougi. + # ⚠ `409` est ACCEPTÉ et nommé : republier une version inchangée n'est + # pas une faute, c'est le cas normal d'un lot qui ne touche pas au + # `version:` du chart. Tout autre code arrête le job. + code=$(curl -s -o /tmp/publication.out -w '%{http_code}' \ + --user ${{ github.actor }}:${{ secrets.PACKAGES_TOKEN }} \ + -X POST --upload-file ./${chart_package} \ + "${registre}/api/charts") || { echo "✖ curl a échoué (code $?) — le registre est injoignable"; exit 1; } + cat /tmp/publication.out || true + case "$code" in + 2??) echo "✓ ${chart_package} publié (HTTP $code)" ;; + 409) echo "✓ ${chart_package} déjà présent au registre (HTTP 409) — rien à republier" ;; + *) echo "✖ publication REFUSÉE (HTTP $code) — le chart n'est PAS au registre"; exit 1 ;; + esac application-charts: <<: *charts-matrix-job