ci : refonte complète de la chaîne — tâches qui s'expliquent, chaîne qui se contrôle elle-même #158

Merged
gabriel merged 13 commits from lenaic/ci-refonte-anglais into develop 2026-09-07 12:22:49 +00:00
Owner

Ce que ça change

La chaîne d'intégration est refondue : chaque tâche se termine par un tableau
qui nomme ses contrôles — avec la raison de ceux qui se sautent, et « échec »
pour ceux qui cassent. Une tâche ouverte dans l'interface ne peut plus paraître
vide, ce qui était le reproche du mini-oral.

La relecture des fichiers a sorti au passage une série de défauts qu'aucun
relecteur humain n'avait vus : un scan de secrets qui passait au vert quand
grep échouait, sept noms d'étapes tronqués depuis toujours, quatre
répertoires de Python jamais lintés.

La chaîne est en français, comme le reste du dépôt. Une première version de
cette PR l'avait passée en anglais à la suite de la remarque du formateur ; après
discussion, l'équipe tient un dépôt d'une seule langue. Le nom du workflow reste
donc Intégration et le motif de protection Intégration / * n'a pas à
changer. La question exacte — « les conventions CI, ou tout le projet ? » — est
à poser au formateur ; ce qui est fait ici ne préjuge pas de sa réponse.

Pas de ticket : ça vient du retour du formateur au mini-oral du 04/09 (rapporté
par Justine), pas du backlog. À rattacher si vous en ouvrez un.

Preuve

L'état avant, sur develop :

$ zizmor --offline --persona=regular .forgejo/workflows/*.yml
    12 unpinned-uses · 7 excessive-permissions · 6 artipacked
$ actionlint .forgejo/workflows/*.yml
    3x actions/upload-artifact@v3 « too old » · 8x label "docker" is unknown

$ python3 -c "import yaml; ..."      # ce que YAML lit vraiment
  job python : 'Faire confiance au CA local de Caddy (ticket'
  job images : 'Non-régression du déploiement continu (ticket'
  ... 7 noms amputés au total

Dans un scalaire YAML non protégé, « espace + # » ouvre un commentaire. Le
fichier reste valide, donc rien ne le signalait.

Après, sur cette branche :

actionlint 0   ·   zizmor 0   ·   yamllint 0   ·   shellcheck (15 scripts) 0
ruff sur services packages infra .forgejo bin db : 0
10 bancs tests/ci : tous verts   ·   pytest tests/unit : 601 passés

Chaque commit pris isolément, dans un arbre neuf, est vert.

L'épinglage par empreinte a été mesuré contre le miroir que le runner utilise
vraiment
, data.forgejo.org — après un premier passage qui avait vérifié le
mauvais hôte et fait échouer la chaîne :

actions/cache            0057852bfaa8…  OK -> refs/tags/v4
actions/checkout         34e114876b0b…  OK -> refs/tags/v4.3.1
actions/upload-artifact  ff15f0306b3f…  OK -> refs/heads/v3/node16

Et defaults.run.shell: sh n'est pas cosmétique — sans elle actionlint
suppose bash et passe nos blocs à shellcheck en bash :

[[ ]] et $SECONDS injectés dans le fichier
  sans la déclaration : AUCUN constat
  avec                : SC3010 + SC3028

Relecture

  • Un pair a relu et laissé un commentaire, même court
  • Ses remarques sont traitées, ou une réponse explique pourquoi elles ne le sont pas

Ce qui suit le code

  • docs/runbooks/ mis à jour, un geste d'exploitation a changé

Où regarder en priorité

1. Rien à changer côté protection de branche. Le workflow s'appelle
toujours Intégration, le motif Intégration / * reste valide. (Une version
intermédiaire de cette PR le renommait CI — c'est fini.)

2. ruff couvre maintenant services packages infra .forgejo bin db. Quatre
répertoires y échappaient, dont les scripts de la chaîne elle-même — un bloc
d'imports non trié y dormait. tests/ reste dehors, et c'est écrit :
15 erreurs et 23 fichiers sur 55 à reformater, écrits par plusieurs personnes.
Décision d'équipe, pas effet de bord. Conséquence pour la #152 : le relais
d'alerte sous infra/ porte un E741 et deux blocs non formatés, la chaîne le
dira désormais.

3. Trois constats réels que je n'ai pas voulu trancher seul — antérieurs à
cette PR, ils engagent l'équipe :

  • deploy.yml ne dépend pas de la CI. push: main, sans workflow_run ni
    needs. Sur un exécuteur unique, le déploiement peut passer avant la
    chaîne. La « barrière » est une convention de merge, pas un mécanisme.
  • La production est déployée depuis inventory/hosts.ini.example. Ce
    fichier EST l'inventaire de production, et son nom dit le contraire. Deux
    garde-fous ajoutés (test-deploiement-continu.sh), le nom reste à trancher.
  • pip-audit --strict confond panne PyPI et CVE. Une indisponibilité bloque
    une PR que personne ne peut débloquer — ce que la doctrine du dépôt interdit
    ailleurs (verdict-audit-npm.js).

4. Deux décisions assumées, à contredire si vous n'êtes pas d'accord.

  • actions/upload-artifact reste en v3. La v4 exige le backend d'artefacts
    de Gitea 1.22+, que l'instance a, mais l'action officielle fait un contrôle
    GHES auquel le backend Forgejo ne répond pas d'après la documentation amont
    — ce n'est pas mesuré ici. Report, pas verdict.
  • Les tâches images et secrets fusionnent en repo. Toutes deux ne
    lisaient que des fichiers sur l'image nue : deux démarrages de conteneur pour
    quelques secondes, sur un exécuteur où les tâches font la queue. La nouvelle
    tâche meta (la chaîne se lint elle-même : actionlint + shellcheck, zizmor,
    yamllint) reprend ce budget. Quatre tâches avant, quatre après.

5. Le défaut qui ne se voit pas d'ici. core.filemode est à false sur
mon poste : mes chmod +x n'étaient pas enregistrés. La chaîne aurait répondu
« Permission denied » partout. Corrigé, et test-hygiene-workflows.sh lit
désormais le mode dans git, pas sur le disque.

## Ce que ça change La chaîne d'intégration est refondue : chaque tâche se termine par un tableau qui nomme ses contrôles — avec la raison de ceux qui se sautent, et « échec » pour ceux qui cassent. Une tâche ouverte dans l'interface ne peut plus paraître vide, ce qui était le reproche du mini-oral. La relecture des fichiers a sorti au passage une série de défauts qu'aucun relecteur humain n'avait vus : un scan de secrets qui passait au vert quand `grep` échouait, sept noms d'étapes tronqués depuis toujours, quatre répertoires de Python jamais lintés. **La chaîne est en français, comme le reste du dépôt.** Une première version de cette PR l'avait passée en anglais à la suite de la remarque du formateur ; après discussion, l'équipe tient un dépôt d'une seule langue. Le nom du workflow reste donc `Intégration` et le motif de protection `Intégration / *` n'a pas à changer. La question exacte — « les conventions CI, ou tout le projet ? » — est à poser au formateur ; ce qui est fait ici ne préjuge pas de sa réponse. Pas de ticket : ça vient du retour du formateur au mini-oral du 04/09 (rapporté par Justine), pas du backlog. À rattacher si vous en ouvrez un. ## Preuve L'état **avant**, sur `develop` : ``` $ zizmor --offline --persona=regular .forgejo/workflows/*.yml 12 unpinned-uses · 7 excessive-permissions · 6 artipacked $ actionlint .forgejo/workflows/*.yml 3x actions/upload-artifact@v3 « too old » · 8x label "docker" is unknown $ python3 -c "import yaml; ..." # ce que YAML lit vraiment job python : 'Faire confiance au CA local de Caddy (ticket' job images : 'Non-régression du déploiement continu (ticket' ... 7 noms amputés au total ``` Dans un scalaire YAML non protégé, « espace + `#` » ouvre un commentaire. Le fichier reste valide, donc rien ne le signalait. **Après**, sur cette branche : ``` actionlint 0 · zizmor 0 · yamllint 0 · shellcheck (15 scripts) 0 ruff sur services packages infra .forgejo bin db : 0 10 bancs tests/ci : tous verts · pytest tests/unit : 601 passés ``` Chaque commit pris isolément, dans un arbre neuf, est vert. L'épinglage par empreinte a été **mesuré contre le miroir que le runner utilise vraiment**, `data.forgejo.org` — après un premier passage qui avait vérifié le mauvais hôte et fait échouer la chaîne : ``` actions/cache 0057852bfaa8… OK -> refs/tags/v4 actions/checkout 34e114876b0b… OK -> refs/tags/v4.3.1 actions/upload-artifact ff15f0306b3f… OK -> refs/heads/v3/node16 ``` Et `defaults.run.shell: sh` n'est pas cosmétique — sans elle `actionlint` suppose bash et passe nos blocs à `shellcheck` en bash : ``` [[ ]] et $SECONDS injectés dans le fichier sans la déclaration : AUCUN constat avec : SC3010 + SC3028 ``` ## Relecture - [ ] Un pair a relu et laissé un commentaire, même court - [ ] Ses remarques sont traitées, ou une réponse explique pourquoi elles ne le sont pas ## Ce qui suit le code - [x] `docs/runbooks/` mis à jour, un geste d'exploitation a changé ## Où regarder en priorité **1. Rien à changer côté protection de branche.** Le workflow s'appelle toujours `Intégration`, le motif `Intégration / *` reste valide. (Une version intermédiaire de cette PR le renommait `CI` — c'est fini.) **2. `ruff` couvre maintenant `services packages infra .forgejo bin db`.** Quatre répertoires y échappaient, dont les scripts de la chaîne elle-même — un bloc d'imports non trié y dormait. `tests/` reste dehors, **et c'est écrit** : 15 erreurs et 23 fichiers sur 55 à reformater, écrits par plusieurs personnes. Décision d'équipe, pas effet de bord. **Conséquence pour la #152** : le relais d'alerte sous `infra/` porte un E741 et deux blocs non formatés, la chaîne le dira désormais. **3. Trois constats réels que je n'ai pas voulu trancher seul** — antérieurs à cette PR, ils engagent l'équipe : - **`deploy.yml` ne dépend pas de la CI.** `push: main`, sans `workflow_run` ni `needs`. Sur un exécuteur unique, le déploiement peut passer **avant** la chaîne. La « barrière » est une convention de merge, pas un mécanisme. - **La production est déployée depuis `inventory/hosts.ini.example`.** Ce fichier EST l'inventaire de production, et son nom dit le contraire. Deux garde-fous ajoutés (`test-deploiement-continu.sh`), le nom reste à trancher. - **`pip-audit --strict` confond panne PyPI et CVE.** Une indisponibilité bloque une PR que personne ne peut débloquer — ce que la doctrine du dépôt interdit ailleurs (`verdict-audit-npm.js`). **4. Deux décisions assumées, à contredire si vous n'êtes pas d'accord.** - `actions/upload-artifact` reste en **v3**. La v4 exige le backend d'artefacts de Gitea 1.22+, que l'instance a, mais l'action officielle fait un contrôle GHES auquel le backend Forgejo ne répond pas *d'après la documentation amont* — ce n'est pas mesuré ici. Report, pas verdict. - Les tâches `images` et `secrets` fusionnent en `repo`. Toutes deux ne lisaient que des fichiers sur l'image nue : deux démarrages de conteneur pour quelques secondes, sur un exécuteur où les tâches font la queue. La nouvelle tâche `meta` (la chaîne se lint elle-même : actionlint + shellcheck, zizmor, yamllint) reprend ce budget. Quatre tâches avant, quatre après. **5. Le défaut qui ne se voit pas d'ici.** `core.filemode` est à `false` sur mon poste : mes `chmod +x` n'étaient pas enregistrés. La chaîne aurait répondu « Permission denied » partout. Corrigé, et `test-hygiene-workflows.sh` lit désormais le mode **dans git**, pas sur le disque.
Les tâches de la chaîne démarrent toujours, ce sont leurs étapes qui se
sautent — c'est voulu, une tâche filtrée par « on.paths » ne démarre pas et
bloque pour toujours un contrôle obligatoire. Mais une tâche pouvait finir
verte avec toutes ses étapes utiles sautées et rien pour le dire : ouverte
dans l'interface, elle paraissait vide. C'est le reproche formulé en
relecture.

Ce script enregistre un résultat par contrôle et rend un tableau en fin de
tâche : le contrôle, son résultat, et pour les sautés la raison. Écrit dans
GITHUB_STEP_SUMMARY quand l'exécuteur en propose un, et dans tous les cas
dans le journal — ce runner n'est pas documenté comme les supportant, la
sortie ne peut donc pas en dépendre.

POSIX strict : les étapes tournent sous « sh -e », et le sh de Debian est
dash.

Le banc l'exécute contre neuf cas plutôt que de le lire, dont les deux qui
comptent : un décompte qui contredit son propre tableau, et un rapport vide
qui se rendrait en silence. Un résumé qui ment est pire que pas de résumé,
parce qu'il est cru.
Reproche de relecture : la chaîne est en français et ses tâches ne disent pas
ce qu'elles font. Les deux sont traités, et la relecture des fichiers en a
sorti quatre défauts que personne n'avait vus.

CE QUI SE VOYAIT
- Tout passe en anglais : noms de workflows, de tâches, d'étapes, et sorties.
- Chaque tâche se termine par une étape « Report » en if: always() qui rend le
  tableau des contrôles. Une étape sautée y dit pourquoi.

CE QUI NE SE VOYAIT PAS
- SEPT NOMS D'ÉTAPES ÉTAIENT TRONQUÉS. « name: ... (ticket #77) » vaut, pour
  YAML, « ... (ticket » suivi d'un commentaire. L'interface affichait le nom
  amputé depuis toujours ; le fichier restant valide, rien ne le signalait.
- Aucun bloc « permissions: », nulle part. Ajouté, en lecture seule.
- Les quatre « checkout » laissaient leur jeton dans .git/config. Aucun ne
  pousse : persist-credentials: false.
- Douze actions référencées par tag. Épinglées par empreinte de commit.

L'épinglage a demandé de vérifier d'abord : cette forge résout les actions
depuis code.forgejo.org, pas github.com (aucun DEFAULT_ACTIONS_URL n'est posé).
Les empreintes du miroir ont été comparées tag par tag à celles de github.com
pour checkout, cache et upload-artifact : identiques. C'est le point resté
ouvert du runbook, refermé.

upload-artifact RESTE EN v3, délibérément. La v4 exige le backend d'artefacts
de Gitea 1.22+, que l'instance a, mais l'action officielle fait un contrôle
GHES auquel le backend Forgejo ne répond pas.

NOUVELLE TÂCHE « meta » : la chaîne se contrôle elle-même — actionlint
(+ shellcheck sur chaque bloc run:), zizmor, yamllint. zizmor rendait 25
constats sur l'ancienne chaîne, il en rend zéro.

COÛT NET NUL SUR UN EXÉCUTEUR UNIQUE. « images » et « secrets » ne lisaient
que des fichiers sur l'image nue : fusionnées en « repo ». Quatre démarrages
de conteneur avant, quatre après, un contrôle de plus. La granularité ne se
perd pas, le tableau de résumé nomme chaque contrôle.

Le banc d'hygiène refuse le retour de chacun de ces défauts, et refuse aussi
qu'un banc soit ajouté sans être joué.
Leur sortie s'affiche dans le journal de la chaîne : la laisser en français
laissait le reproche à moitié traité.

Traduction seule, logique inchangée — sauf deux points relevés en chemin :

- test-supervision.sh validait le JSON des tableaux de bord avec python3,
  alors que l'en-tête de la chaîne affirme qu'il n'y a pas d'interpréteur
  Python sur l'image du libellé. Le contrôle ne passait que parce que
  node:22-bookworm embarque python3 pour node-gyp. Le jour où l'image maigrit,
  tous les tableaux de bord seraient déclarés « JSON invalide », ce qui est
  faux et envoie chercher au mauvais endroit. Bascule sur node, seul
  interpréteur que cette tâche peut garantir.

- test-deploiement-continu.sh cherchait « repo_version=...github.sha » en
  clair. La valeur passe maintenant par une variable d'environnement, pour ne
  pas dilater d'expression dans du shell. Le banc suit la valeur au lieu de
  l'orthographe : il remonte de repo_version=$VAR à l'entrée env qui définit
  VAR et exige qu'elle vienne de github.sha. Éprouvé sur deux sabotages —
  github.ref à la place de github.sha, et repo_version figé en dur.

verifier-images.sh et son banc changent ensemble : le banc assertait sur le
texte du rapport. Idem pour verdict-audit-npm.js et le sien.

deps-services.py : sortie vérifiée identique à l'ancienne version.

tests/ci/test-role-app.yml reste en français, volontairement : c'est un
playbook Ansible, joué par la tâche Ansible, à côté de rôles qui restent en
français. La frontière est là — la chaîne parle anglais, l'infrastructure
qu'elle pilote reste en français.
Le tableau des tâches, les noms affichés et le motif de contrôle obligatoire
étaient devenus faux.

Ajouté : ce que fait la tâche « meta » et comment la jouer à la main, et la
section sur le résumé de tâche — pourquoi il existe et où il s'écrit.

Refermé : le point resté ouvert sur l'épinglage des actions, avec ce que la
vérification du miroir a montré. Ajouté à la place : pourquoi upload-artifact
reste en v3.

AVERTISSEMENT CONSERVÉ EN TÊTE : le motif obligatoire est préfixé par le nom
du workflow. « Intégration » devient « CI », les deux règles de protection
(develop et main) doivent donc passer de « Intégration / * » à « CI / * ». Une
tâche qui ne correspond à aucun motif obligatoire reste « en attente » pour
toujours et bloque sans rien expliquer.

docs/FORGE.md et le commentaire du Dockerfile mlflow nommaient des tâches qui
n'existent plus.
ci : durcissement après relecture hostile de la chaîne
Some checks failed
CI / Repository static checks (pull_request) Successful in 13s
CI / Python — quality, tests and dependencies (pull_request) Failing after 1m1s
CI / Dashboard — dependencies, tests and build (pull_request) Failing after 59s
CI / Workflows — lint and security audit (pull_request) Successful in 1m1s
Infra Ansible / Ansible playbooks are valid (pull_request) Successful in 53s
e10f60b07c
Deux relectures indépendantes de la refonte : la mienne, et une passe d'audit
sans aucun contexte du projet. Elles ont convergé sur le même défaut central et
en ont sorti une quinzaine d'autres. Ce que ça change :

LE RÉSUMÉ D'UN JOB ROUGE OMETTAIT CE QUI AVAIT CASSÉ. Les étapes tournent sous
« sh -e » : une commande en échec interrompt l'étape avant sa ligne de rapport,
donc le contrôle disparaissait du tableau. Le correctif est
.forgejo/scripts/ci-run.sh, qui lance la commande, enregistre dans les deux cas
et rend le code de sortie. Son banc a trouvé deux défauts dans le lanceur
lui-même : un code capté après un « if ... fi » (c'est celui du if), et « sh -e »
qui franchit le shebang quand on invoque « sh -e ci-run.sh ».

UN SCAN DE SECRETS QUI PASSAIT AU VERT SUR UNE ERREUR. grep rend 2 quand il ne
peut pas lire un fichier — non nul, donc la branche « rien trouvé ». Et il rend
2 même s'il a AUSSI trouvé : les lignes s'affichaient au-dessus d'un rapport
disant le contraire. Les trois issues sont séparées. Les motifs rataient par
ailleurs les formes les plus probables ici : PKCS#8 (« BEGIN PRIVATE KEY », ce
que produit ssh-keygen aujourd'hui) et la syntaxe YAML « password: valeur ». Un
premier motif élargi rendait dix faux positifs sur ce dépôt — un contrôle rouge
sur du code correct finit désarmé — il exige donc une valeur littérale entre
guillemets, sans interpolation. Éprouvé : cinq formes réelles attrapées, les dix
lignes légitimes ignorées.

UNE PANNE DU VERDICT npm ÉTAIT ANNONCÉE COMME UNE CVE CRITIQUE. La branche
« *) » attrapait aussi 127 (node absent) et 126 (bit d'exécution) : accusation
fausse et bloquante, dans le job dont tout le propos est de ne pas confondre les
causes.

actionlint LISAIT UN SHELL QU'ON N'EXÉCUTE PAS. Sans « defaults.run.shell: sh »
il suppose bash. Éprouvé : un « [[ ]] » et un « $SECONDS » injectés ne
produisent AUCUN constat sans la déclaration, SC3010 et SC3028 avec. Et
actionlint ne lit que les blocs « run: » — nos propres scripts n'étaient
analysés par personne, d'où l'étape shellcheck.

Le reste, plus court :
- un job mort avant ses scans affirmait « aucun Python dans le dépôt » ; une
  sortie vide n'est pas un « non ».
- un service sans [tool.mypy] était sauté sans un mot, sous un commentaire qui
  jurait le contraire.
- un fichier de certificat absent était diagnostiqué « expiré ». Et « -checkend 0 »
  ne prévenait jamais : trente jours de préavis en avertissement.
- la confiance au CA était posée après les étapes bloquantes, alors que les
  envois d'artefacts sont en « if: always() » : sur un job rouge ils partaient
  sans elle.
- « services/**/x » ne matche pas « services/x » : un service à plat échappait
  au typage et à l'audit.
- « infra/compose/*.yml » balayait tout le sous-arbre et donnait prometheus.yml
  et la config du runner au contrôleur d'images.
- ssh-keyscan en échec tuait l'étape avant son propre message d'erreur.
- tests/ci/test-role-app.yml était hors des paths du workflow qui le joue.
- un « | » dans un détail cassait les colonnes du tableau.
- deps-services.py tournait deux fois pour le même résultat.

Et sept commentaires qui affirmaient faux, dont « git n'est pas requis par
checkout » — il l'est, et sans lui « git ls-files » rendrait vide, laissant
trois contrôles verts sans rien lire.
ci : épingler contre le miroir que le runner utilise vraiment
All checks were successful
CI / Repository static checks (pull_request) Successful in 52s
CI / Workflows — lint and security audit (pull_request) Successful in 28s
CI / Dashboard — dependencies, tests and build (pull_request) Successful in 1m23s
Infra Ansible / Ansible playbooks are valid (pull_request) Successful in 53s
CI / Python — quality, tests and dependencies (pull_request) Successful in 4m22s
88d8330e6c
La chaîne a échoué au premier passage réel sur « Unable to resolve
0057852bfaa8b1baaa5b6f4c37c1fca1e70e02a3: reference not found ».

Ce runner résout les actions depuis data.forgejo.org. Les empreintes avaient
été vérifiées contre code.forgejo.org — un autre hôte Forgejo — où elles
correspondaient bien à celles de github.com, ce qui a été pris pour une preuve.
Ce n'en était pas une : le miroir servi n'est pas une copie à l'identique.
checkout@v4.3.1 y porte le même commit, cache@v4 non.

  cache@v4  data.forgejo.org : 0057852bfaa89a56745cba8c7296529d2fc39830
  cache@v4  github.com       : 0057852bfaa8b1baaa5b6f4c37c1fca1e70e02a3

Douze caractères communs en tête. L'œil glisse dessus, et une comparaison
tronquée à l'affichage aussi.

Les trois empreintes sont désormais vérifiées une par une contre
data.forgejo.org, et l'en-tête du fichier donne la seule commande qui vaut
preuve. Le runbook dit ce que l'épinglage achète — l'immuabilité sur l'hôte qui
sert l'action — et ce qu'il n'achète pas : la certitude que le code est celui
publié en amont. Comparer des identifiants n'est pas comparer des arbres.
docs(ci) : les résumés de tâche sont supportés, c'est mesuré
All checks were successful
CI / Repository static checks (pull_request) Successful in 7s
CI / Dashboard — dependencies, tests and build (pull_request) Successful in 18s
CI / Workflows — lint and security audit (pull_request) Successful in 19s
Infra Ansible / Ansible playbooks are valid (pull_request) Successful in 54s
CI / Python — quality, tests and dependencies (pull_request) Successful in 3m23s
0bd78d3e86
Le rendu a été écrit pour marcher avec ou sans GITHUB_STEP_SUMMARY, Forgejo ne
documentant pas cette variable. L'exécution 1424 du 2026-09-05 tranche : le
runner la fournit, les tableaux atteignent donc l'interface web et pas
seulement le journal. Le repli reste — il coûte une branche, et c'est lui qui
rendait la question sans conséquence.
ci: linte tout le Python du dépôt, pas seulement services et packages
All checks were successful
CI / Repository static checks (pull_request) Successful in 7s
CI / Dashboard — dependencies, tests and build (pull_request) Successful in 19s
CI / Workflows — lint and security audit (pull_request) Successful in 17s
Infra Ansible / Ansible playbooks are valid (pull_request) Successful in 1m29s
CI / Python — quality, tests and dependencies (pull_request) Successful in 3m28s
8212486bb0
L'étape nommait « services packages » et rien d'autre. Tout le Python vivant
ailleurs échappait donc à Ruff, à son contrôle de format et à tout le reste —
pendant que la chaîne annonçait « Ruff | passed », ce qui était vrai, sur des
répertoires qu'elle n'avait jamais ouverts. Un vert qui ne mesure rien.

Ce qui passait au travers : infra/compose/mlflow/exemple-execution.py,
bin/_sonde_api.py, db/migrate.py, et .forgejo/scripts/deps-services.py — un
script de cette chaîne elle-même, qui portait un bloc d'imports non trié que
personne ne pouvait voir. Il est corrigé ici. Le relais d'alerte ajouté sous
infra/ par la #152 porte un E741 et deux blocs non formatés pour la même
raison : la chaîne le dira désormais.

La définition de terminé dit « Ruff passe ». Pour ce code, Ruff n'était pas
appelé.

tests/ reste dehors, et c'est écrit plutôt que supposé : mesuré aujourd'hui,
Ruff y rend 15 erreurs et reformaterait 23 fichiers sur 55. Les y faire entrer
demande de réécrire les tests de plusieurs personnes en même temps — une
décision d'équipe, pas l'effet de bord d'une correction. La ligne du banc qui
l'exclut porte la mesure et la raison.

Le banc refuse désormais qu'un répertoire portant du Python sorte de la portée :
il compare ce que « git ls-files '*.py' » trouve à ce que l'étape nomme. Éprouvé
en retirant « infra » de la liste, qui est alors nommé.
lenaic changed title from ci : refonte complète de la chaîne — anglais, tâches qui s'expliquent, chaîne qui se contrôle elle-même to ci : refonte complète de la chaîne — tâches qui s'expliquent, chaîne qui se contrôle elle-même 2026-09-07 07:01:39 +00:00
ci : la chaîne revient au français, comme le reste du dépôt
All checks were successful
Intégration / Contrôles statiques du dépôt (pull_request) Successful in 7s
Intégration / Tableau de bord — dépendances, tests et construction (pull_request) Successful in 20s
Intégration / Workflows — lint et audit de sécurité (pull_request) Successful in 20s
Infra Ansible / Playbooks Ansible valides (pull_request) Successful in 2m32s
Intégration / Python — qualité, tests et dépendances (pull_request) Successful in 3m20s
c54a71339c
La refonte du 04/09 avait passé la chaîne d'intégration en anglais, à la suite
d'une remarque de formateur en mini-oral. Le dépôt est en français partout
ailleurs — code, commentaires, documentation, rôles Ansible, tickets. Tenir
deux langues dans un même projet n'est pas une convention, c'est une frontière
qui court là où le dernier chantier s'est arrêté : `infra/ansible` et
`.forgejo/` sont deux couches d'infrastructure, lues par les mêmes personnes en
panne, et l'une était en français quand l'autre était en anglais. Décision du
07/09 : une seule langue, celle du dépôt.

Traduction, pas refonte. La structure, les étapes, les commandes, les
empreintes d'actions, `defaults.run.shell: sh`, les `permissions:` et la
logique de chaque contrôle sont inchangés. Se traduisent les noms affichés
(workflows, tâches, étapes), les commentaires, les messages et annotations,
les noms de contrôles du tableau de résumé et son rendu. Restent tels quels
les identifiants — ids de jobs et d'étapes, clés de sortie (`found=yes`),
variables d'environnement, statuts du protocole de `ci-report.sh` (`passed`,
`failed`, `skipped`, `warned`, `missing`), noms de fichiers — parce qu'un
identifiant n'est pas lu, il est référencé, et le renommer n'apporte que des
occasions de casser.

Les couples script/banc ont été traduits ensemble : les bancs assertent sur
les messages des scripts (`image non épinglée :`, `illisible`, `registre`,
`code N, voir le journal de l'étape ci-dessus`), et une traduction séparée les
aurait désaccordés. Les libellés français d'origine sont repris mot pour mot
là où ils existaient.

Une conséquence heureuse : le workflow reprend son nom, `Intégration`. Le
motif de contrôle obligatoire `Intégration / *` des règles de protection de
`develop` et `main` redevient valide tel quel — il n'y a plus rien à changer
côté forge au moment de la fusion. Le runbook et les documents qui citaient
`CI / *` et les noms anglais des tâches sont réalignés.

Le contrôle d'hygiène qui refusait les lettres accentuées dans les noms
affichés est inversé : il refuse désormais les restes d'anglais évidents dans
un `name:`, par une liste de mots volontairement étroite — élargir ferait
rougir du français correct, et un banc qui crie faux finit débranché. Appliqué
aux versions anglaises, il signalait 41 noms ; aux françaises, zéro.

`docs/CONVENTIONS.md` gagne la section « Langue » qu'il n'avait pas, et qui
aurait évité la dérive : tout est en français, chaîne comprise, et la
question exacte du formateur — les conventions CI, ou tout le projet ? — reste
à lui poser avant de décider quoi que ce soit d'un bloc.

Vérifié : actionlint, yamllint, zizmor, shellcheck (scripts sh et bancs) et
ruff à zéro constat ; les dix bancs de tests/ci verts ; aucun nom d'étape
tronqué au chargement YAML ; `deps-services.py` rend une sortie identique.
lenaic requested review from gabriel 2026-09-07 07:06:37 +00:00
lenaic self-assigned this 2026-09-07 07:25:17 +00:00
gabriel approved these changes 2026-09-07 11:01:28 +00:00
Dismissed
Merge develop dans la refonte de la chaîne (#158)
Some checks failed
Intégration / Tableau de bord — dépendances, tests et construction (pull_request) Successful in 31s
Intégration / Contrôles statiques du dépôt (pull_request) Failing after 6s
Intégration / Workflows — lint et audit de sécurité (pull_request) Successful in 25s
Infra Ansible / Playbooks Ansible valides (pull_request) Successful in 1m22s
Intégration / Python — qualité, tests et dépendances (pull_request) Successful in 3m28s
2a432c6c5a
# Conflicts:
#	.forgejo/workflows/ci.yml
lenaic dismissed gabriel's review 2026-09-07 11:12:19 +00:00
Reason:

New commits pushed, approval review dismissed automatically according to repository settings

ci: le contrôle des secrets n'est plus rouge sur un test unitaire sain (#158)
All checks were successful
Intégration / Contrôles statiques du dépôt (pull_request) Successful in 8s
Intégration / Tableau de bord — dépendances, tests et construction (pull_request) Successful in 32s
Intégration / Workflows — lint et audit de sécurité (pull_request) Successful in 25s
Infra Ansible / Playbooks Ansible valides (pull_request) Successful in 1m4s
Intégration / Python — qualité, tests et dépendances (pull_request) Successful in 3m23s
e61f26e1fd
services/dashboard/tests/unit/authentification.test.js, arrivé avec develop,
affecte un littéral de neuf caractères au champ d'identification d'un
utilisateur d'essai. C'est la forme exacte que le motif cherche, et c'est du
code parfaitement correct : le job « Contrôles statiques du dépôt » est passé
rouge sur cette branche pour ça.

Les arbres de tests sont donc exclus, comme le sont déjà les fixtures et les
fichiers d'exemple. Un identifiant d'essai dans un test unitaire est normal ;
un secret qui fuit ne vit pas là. Le commentaire du contrôle disait déjà
pourquoi un contrôle rouge sur du code sain est désarmé dans la semaine.

Au passage : la première rédaction de ce commentaire citait le littéral en
toutes lettres et déclenchait le contrôle qu'elle explique. Elle le décrit
maintenant.
Merge branch 'develop' into lenaic/ci-refonte-anglais
All checks were successful
Intégration / Tableau de bord — dépendances, tests et construction (pull_request) Successful in 33s
Intégration / Contrôles statiques du dépôt (pull_request) Successful in 6s
Intégration / Workflows — lint et audit de sécurité (pull_request) Successful in 19s
Infra Ansible / Playbooks Ansible valides (pull_request) Successful in 1m14s
Intégration / Python — qualité, tests et dépendances (pull_request) Successful in 3m46s
ffcd6de54e
Merge branch 'develop' into lenaic/ci-refonte-anglais
All checks were successful
Infra Ansible / Playbooks Ansible valides (pull_request) Successful in 1m9s
Intégration / Tableau de bord — dépendances, tests et construction (pull_request) Successful in 34s
Intégration / Contrôles statiques du dépôt (pull_request) Successful in 6s
Intégration / Workflows — lint et audit de sécurité (pull_request) Successful in 20s
Intégration / Python — qualité, tests et dépendances (pull_request) Successful in 3m49s
50a0e0f014
gabriel merged commit 24d6dbcf15 into develop 2026-09-07 12:22:49 +00:00
gabriel deleted branch lenaic/ci-refonte-anglais 2026-09-07 12:22:50 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
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
g2/enervision!158
No description provided.