test-curl.sh : contourner les proxys de l'environnement, comme boot-from-copy.sh #41

Closed
opened 2026-10-01 00:56:27 +00:00 by maximus · 0 comments
Owner

Constat relevé pendant #35, hors de son périmètre. Analyse du 2026-10-01 : prémisse remesurée et confirmée, épingle et portée arrêtées.

Contexte

Depuis #35, scripts/boot-from-copy.sh exporte NO_PROXY='*' et no_proxy='*' en tête (l. 28) : tous ses curl visent la boucle locale, et un proxy de l'environnement répondrait à la place du serveur démarré. test-curl.sh a la même exposition, sans aucun contournement : 18 lignes de code y appellent curl vers ses propres serveurs (3099 et 3098), dont les deux boucles d'attente (l. 163 et 167) et les wrappers http_code et http_body (l. 188 et 191).

Remesuré le 2026-10-01 sur main (198e1cf) : http_proxy=http://127.0.0.1:9 bash test-curl.sh sort en code 7 après 11,3 s, avec 0 octet de sortie. Les deux boucles d'attente épuisent leurs 5 s sans joindre les serveurs, puis le premier code=$(curl ...) (cas 1, l. 195, hors wrapper) échoue sur la connexion refusée par le proxy, et set -e arrête le script sans un mot. L'échec est franc par le code de sortie, ce n'est pas un faux vert, mais il ne donne aucun diagnostic. Avec un proxy qui répond, les cas recevraient les réponses du proxy au lieu de celles de l'API.

Sans proxy, le script passe ses 45 cas en 1,6 s. Le coût d'un passage complet sous vitest, que la première version de cette issue craignait, est donc faible.

Décisions

  1. Correctif : la ligne export NO_PROXY='*' no_proxy='*' en tête de test-curl.sh, avec le même commentaire que boot-from-copy.sh (curl lit d'abord la minuscule, d'où les deux graphies).
  2. Épingle : passage complet sous vitest, sur le modèle du test never sends a request through a proxy from the environment de __tests__/ci.test.js : faux proxy qui répond à tout et enregistre ce qui l'atteint, vivacité prouvée d'abord par un curl nu, environnement http_proxy + ALL_PROXY + no_proxy=example.invalid avec NO_PROXY retiré, puis bash test-curl.sh : rien n'atteint le proxy, sortie 0. Les variantes écartées : un proxy mort dans l'étape CI (rien en local, ne montre pas le proxy qui répond) et une épingle sur le source (lit du texte, pas un comportement).
  3. Portée élargie : échec bruyant des boucles d'attente. Quand un serveur ne répond pas au bout des 5 s, le script écrit un message sur stderr qui nomme l'URL et sort en 1, au lieu de continuer jusqu'au premier curl nu. Cela vaut pour toute cause de non-démarrage (port pris, plantage au boot), pas seulement le proxy.

Travail à faire

  • test-curl.sh : export des deux graphies avant le premier curl, avec son commentaire.
  • test-curl.sh : après chaque boucle d'attente, détecter l'épuisement (drapeau posé au break, ou for ... else simulé), message sur stderr, exit 1. Le trap EXIT existant nettoie déjà les serveurs et le dossier temporaire.
  • __tests__/ci.test.js : nouveau describe("test-curl.sh") avec le cas du faux proxy. Réutiliser run() ; runBootScript reste propre au boot check. Délai de test à fixer d'après la mesure (1,6 s nominal).
  • __tests__/ci.test.js : un cas pour l'échec bruyant, par exemple un voisin qui tient déjà 3099 et 3098 n'est pas un bon témoin (il répondrait à la boucle) ; préférer un node introuvable ou un PATH qui fait échouer le démarrage, à trancher à l'implémentation, avec message et code 1 exigés.
  • CLAUDE.md : paragraphe bash test-curl.sh de la section Tests (contournement des proxys, échec bruyant), compte de cas de ci.test.js et total de npm test.

Fichiers concernés

  • test-curl.sh : en-tête (après set -euo pipefail, l. 19) et boucles d'attente (l. 161 à 169).
  • __tests__/ci.test.js : helpers run() et freePort() déjà présents (l. 130 à 157), modèle du test à suivre l. 180 à 216.
  • CLAUDE.md : section Tests.
  • .forgejo/workflows/ci.yml : aucun changement.

Surface de test

  • Tests existants : bash test-curl.sh lui-même (45 cas, étape CI « Socket-level pass ») ; __tests__/ci.test.js (25 cas) couvre le workflow et boot-from-copy.sh, rien sur test-curl.sh.
  • Tests manquants : le passage derrière un faux proxy, et l'échec bruyant d'une boucle d'attente.
  • Preuve par mutation attendue : retirer l'export fait rougir le nouveau test ; n'exporter que NO_PROXY aussi.

Risques

  • Ports fixes. test-curl.sh démarre ses serveurs sur 3099 et 3098 en dur (BASE_URL se surcharge, pas le PORT du serveur). Lancé depuis vitest, il échoue si un autre processus tient ces ports pendant npm test, et deux npm test simultanés se gênent. En CI, l'étape « Socket-level pass » tourne après npm test, sans recouvrement. Avec l'échec bruyant, une collision devient au moins lisible. Rendre les ports paramétrables est hors périmètre, à ouvrir en issue séparée si le cas se présente.
  • Le serveur Node démarré par le script n'utilise pas le proxy de l'environnement (Node 22 ne lit pas http_proxy), et LOGTO_HEALTH_URL pointe sur un port fermé : seuls les curl sont concernés.

Critères d'acceptation

  • http_proxy=http://127.0.0.1:9 bash test-curl.sh passe ses 45 cas, sortie 0.
  • Un test vitest lance test-curl.sh derrière un faux proxy qui répond à tout, avec no_proxy hérité qui laisse la boucle locale hors liste : aucune requête ne l'atteint, sortie 0. Vivacité du proxy prouvée dans le même test.
  • Mutations : sans l'export, et avec NO_PROXY seul, le test rougit.
  • Un serveur qui ne démarre pas produit un message sur stderr et un code de sortie 1, épinglé par un test.
  • npm test et bash test-curl.sh verts, CI verte, comptes de cas de CLAUDE.md à jour.

Complexité estimée

Simple. Deux fichiers de code, une dizaine de lignes dans le script, deux cas de test calqués sur un modèle existant.

Constat relevé pendant #35, hors de son périmètre. Analyse du 2026-10-01 : prémisse remesurée et confirmée, épingle et portée arrêtées. ## Contexte Depuis #35, `scripts/boot-from-copy.sh` exporte `NO_PROXY='*'` et `no_proxy='*'` en tête (l. 28) : tous ses `curl` visent la boucle locale, et un proxy de l'environnement répondrait à la place du serveur démarré. `test-curl.sh` a la même exposition, sans aucun contournement : 18 lignes de code y appellent `curl` vers ses propres serveurs (3099 et 3098), dont les deux boucles d'attente (l. 163 et 167) et les wrappers `http_code` et `http_body` (l. 188 et 191). **Remesuré le 2026-10-01** sur `main` (198e1cf) : `http_proxy=http://127.0.0.1:9 bash test-curl.sh` sort en code 7 après 11,3 s, avec **0 octet de sortie**. Les deux boucles d'attente épuisent leurs 5 s sans joindre les serveurs, puis le premier `code=$(curl ...)` (cas 1, l. 195, hors wrapper) échoue sur la connexion refusée par le proxy, et `set -e` arrête le script sans un mot. L'échec est franc par le code de sortie, ce n'est pas un faux vert, mais il ne donne aucun diagnostic. Avec un proxy qui répond, les cas recevraient les réponses du proxy au lieu de celles de l'API. Sans proxy, le script passe ses 45 cas en **1,6 s**. Le coût d'un passage complet sous vitest, que la première version de cette issue craignait, est donc faible. ## Décisions 1. **Correctif** : la ligne `export NO_PROXY='*' no_proxy='*'` en tête de `test-curl.sh`, avec le même commentaire que `boot-from-copy.sh` (curl lit d'abord la minuscule, d'où les deux graphies). 2. **Épingle : passage complet sous vitest**, sur le modèle du test `never sends a request through a proxy from the environment` de `__tests__/ci.test.js` : faux proxy qui répond à tout et enregistre ce qui l'atteint, vivacité prouvée d'abord par un `curl` nu, environnement `http_proxy` + `ALL_PROXY` + `no_proxy=example.invalid` avec `NO_PROXY` retiré, puis `bash test-curl.sh` : rien n'atteint le proxy, sortie 0. Les variantes écartées : un proxy mort dans l'étape CI (rien en local, ne montre pas le proxy qui répond) et une épingle sur le source (lit du texte, pas un comportement). 3. **Portée élargie : échec bruyant des boucles d'attente.** Quand un serveur ne répond pas au bout des 5 s, le script écrit un message sur stderr qui nomme l'URL et sort en 1, au lieu de continuer jusqu'au premier `curl` nu. Cela vaut pour toute cause de non-démarrage (port pris, plantage au boot), pas seulement le proxy. ## Travail à faire - [ ] `test-curl.sh` : export des deux graphies avant le premier `curl`, avec son commentaire. - [ ] `test-curl.sh` : après chaque boucle d'attente, détecter l'épuisement (drapeau posé au `break`, ou `for ... else` simulé), message sur stderr, `exit 1`. Le `trap EXIT` existant nettoie déjà les serveurs et le dossier temporaire. - [ ] `__tests__/ci.test.js` : nouveau `describe("test-curl.sh")` avec le cas du faux proxy. Réutiliser `run()` ; `runBootScript` reste propre au boot check. Délai de test à fixer d'après la mesure (1,6 s nominal). - [ ] `__tests__/ci.test.js` : un cas pour l'échec bruyant, par exemple un voisin qui tient déjà 3099 et 3098 n'est pas un bon témoin (il répondrait à la boucle) ; préférer un `node` introuvable ou un `PATH` qui fait échouer le démarrage, à trancher à l'implémentation, avec message et code 1 exigés. - [ ] `CLAUDE.md` : paragraphe `bash test-curl.sh` de la section Tests (contournement des proxys, échec bruyant), compte de cas de `ci.test.js` et total de `npm test`. ## Fichiers concernés - `test-curl.sh` : en-tête (après `set -euo pipefail`, l. 19) et boucles d'attente (l. 161 à 169). - `__tests__/ci.test.js` : helpers `run()` et `freePort()` déjà présents (l. 130 à 157), modèle du test à suivre l. 180 à 216. - `CLAUDE.md` : section Tests. - `.forgejo/workflows/ci.yml` : aucun changement. ## Surface de test - Tests existants : `bash test-curl.sh` lui-même (45 cas, étape CI « Socket-level pass ») ; `__tests__/ci.test.js` (25 cas) couvre le workflow et `boot-from-copy.sh`, rien sur `test-curl.sh`. - Tests manquants : le passage derrière un faux proxy, et l'échec bruyant d'une boucle d'attente. - Preuve par mutation attendue : retirer l'export fait rougir le nouveau test ; n'exporter que `NO_PROXY` aussi. ## Risques - **Ports fixes.** `test-curl.sh` démarre ses serveurs sur 3099 et 3098 en dur (`BASE_URL` se surcharge, pas le `PORT` du serveur). Lancé depuis vitest, il échoue si un autre processus tient ces ports pendant `npm test`, et deux `npm test` simultanés se gênent. En CI, l'étape « Socket-level pass » tourne après `npm test`, sans recouvrement. Avec l'échec bruyant, une collision devient au moins lisible. Rendre les ports paramétrables est hors périmètre, à ouvrir en issue séparée si le cas se présente. - Le serveur Node démarré par le script n'utilise pas le proxy de l'environnement (Node 22 ne lit pas `http_proxy`), et `LOGTO_HEALTH_URL` pointe sur un port fermé : seuls les `curl` sont concernés. ## Critères d'acceptation - [ ] `http_proxy=http://127.0.0.1:9 bash test-curl.sh` passe ses 45 cas, sortie 0. - [ ] Un test vitest lance `test-curl.sh` derrière un faux proxy qui répond à tout, avec `no_proxy` hérité qui laisse la boucle locale hors liste : aucune requête ne l'atteint, sortie 0. Vivacité du proxy prouvée dans le même test. - [ ] Mutations : sans l'export, et avec `NO_PROXY` seul, le test rougit. - [ ] Un serveur qui ne démarre pas produit un message sur stderr et un code de sortie 1, épinglé par un test. - [ ] `npm test` et `bash test-curl.sh` verts, CI verte, comptes de cas de `CLAUDE.md` à jour. ## Complexité estimée Simple. Deux fichiers de code, une dizaine de lignes dans le script, deux cas de test calqués sur un modèle existant.
maximus added the
status:ready
type:infra
source:human
labels 2026-10-01 00:56:27 +00:00
maximus added
status:in-progress
and removed
status:ready
labels 2026-10-02 00:08:46 +00:00
maximus added
status:review
and removed
status:in-progress
labels 2026-10-02 00:12:59 +00:00
maximus added
status:needs-fix
and removed
status:review
labels 2026-10-02 00:37:58 +00:00
maximus added
status:review
and removed
status:needs-fix
labels 2026-10-02 00:51:43 +00:00
maximus added
status:approved
and removed
status:review
labels 2026-10-02 01:14:44 +00:00
maximus added
status:review
and removed
status:approved
labels 2026-10-02 01:18:46 +00:00
maximus removed the
status:review
label 2026-10-02 01:25:03 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: maximus/vps-health-api#41
No description provided.