[42] Cinq alertes d'exploitation, notifiées dans la forge #152

Merged
lenaic merged 10 commits from gabriel/42-alertes into develop 2026-09-07 13:09:45 +00:00
Member

Ferme #42 — cinq alertes d'exploitation (ENF-08, EC03).

Moteur : alerting unifié de Grafana, règles provisionnées par fichier (grafana/provisioning/alerting/). Pas d'Alertmanager. Canal unique : un webhook vers relais-forge (nouveau service, ~200 lignes de bibliothèque standard, image python:3.12-alpine montée telle quelle) qui ouvre une issue Forgejo assignée au destinataire nommé par la règle, et la referme à la résolution. Réseau clos : la forge est la seule destination, pas de relais SMTP (décision d'équipe).

Les cinq alertes

Alerte Seuil Destinataire
Collecte arrêtée > 5 min sans passe /current réussie justine
Disque serveur bientôt plein espace libre / < 15 % lenaic
API source lente ou muette sonde blackbox > 2 s ou en échec olivier
Cible de supervision tombée up == 0 lenaic
Sauvegarde PostgreSQL en échec échec, ou > 26 h sans succès lenaic

La dernière ferme l'écart n°4 de docs/POSTGRESQL.md (« aucune alerte sur échec — attend Prometheus »).

Plomberie

  • collecte-current.sh et pg-backup.sh déposent des métriques ev_ops_* dans /var/lib/node_exporter/textfile, republiées par node-exporter (flag --collector.textfile.directory ajouté)
  • blackbox-exporter ajouté à la pile (127.0.0.1:9115) ; job blackbox dans prometheus.yml sonde l'API source, la forge et Grafana
  • rôle app : création du répertoire textfile, garde de vault_forge_alerte_token dans l'assert
  • test-supervision.sh étendu : cinq règles, destinataire nommé, point de contact webhook, aucun jeton en clair, YAML du provisioning valide

Avant de fusionner

Créer le compte de service forge ci-alertes + jeton portée issuevault_forge_alerte_token. Le déploiement échoue tant que le secret est absent (garde dans l'assert du rôle app). Voir docs/runbooks/supervision.md § 7.

Après déploiement

Déclencher une alerte en conditions réelles (renommer /var/backups/postgresql, lancer pg-backup.sh) et joindre l'URL de l'issue horodatée au ticket #42 (preuve ENF-08). Ouvrir un ticket de suivi « régler les seuils après 24 h d'observation ».

Validé localement

Provisioning chargé sans erreur par Grafana 11.6.3 (5 règles + point de contact + politique vus via l'API), promtool check config OK, config blackbox OK (digest confirmé au pull), relais testé (chemins firing et resolved), test-supervision.sh / test-liens-markdown.sh / verifier-images.sh verts.

Ferme #42 — cinq alertes d'exploitation (ENF-08, EC03). Moteur : alerting unifié de Grafana, règles provisionnées par fichier (`grafana/provisioning/alerting/`). Pas d'Alertmanager. Canal unique : un webhook vers `relais-forge` (nouveau service, ~200 lignes de bibliothèque standard, image `python:3.12-alpine` montée telle quelle) qui ouvre une issue Forgejo assignée au destinataire nommé par la règle, et la referme à la résolution. Réseau clos : la forge est la seule destination, pas de relais SMTP (décision d'équipe). ## Les cinq alertes | Alerte | Seuil | Destinataire | |---|---|---| | Collecte arrêtée | > 5 min sans passe `/current` réussie | justine | | Disque serveur bientôt plein | espace libre `/` < 15 % | lenaic | | API source lente ou muette | sonde blackbox > 2 s ou en échec | olivier | | Cible de supervision tombée | `up == 0` | lenaic | | Sauvegarde PostgreSQL en échec | échec, ou > 26 h sans succès | lenaic | La dernière ferme l'écart n°4 de `docs/POSTGRESQL.md` (« aucune alerte sur échec — attend Prometheus »). ## Plomberie - `collecte-current.sh` et `pg-backup.sh` déposent des métriques `ev_ops_*` dans `/var/lib/node_exporter/textfile`, republiées par node-exporter (flag `--collector.textfile.directory` ajouté) - `blackbox-exporter` ajouté à la pile (`127.0.0.1:9115`) ; job `blackbox` dans `prometheus.yml` sonde l'API source, la forge et Grafana - rôle `app` : création du répertoire textfile, garde de `vault_forge_alerte_token` dans l'`assert` - `test-supervision.sh` étendu : cinq règles, destinataire nommé, point de contact webhook, aucun jeton en clair, YAML du provisioning valide ## Avant de fusionner Créer le compte de service forge `ci-alertes` + jeton portée `issue` → `vault_forge_alerte_token`. Le déploiement échoue tant que le secret est absent (garde dans l'`assert` du rôle `app`). Voir `docs/runbooks/supervision.md` § 7. ## Après déploiement Déclencher une alerte en conditions réelles (renommer `/var/backups/postgresql`, lancer `pg-backup.sh`) et joindre l'URL de l'issue horodatée au ticket #42 (preuve ENF-08). Ouvrir un ticket de suivi « régler les seuils après 24 h d'observation ». ## Validé localement Provisioning chargé sans erreur par Grafana 11.6.3 (5 règles + point de contact + politique vus via l'API), `promtool check config` OK, config blackbox OK (digest confirmé au pull), relais testé (chemins firing et resolved), `test-supervision.sh` / `test-liens-markdown.sh` / `verifier-images.sh` verts.
supervision: cinq alertes d'exploitation, notifiées dans la forge (#42)
All checks were successful
Intégration / Contrôles statiques du dépôt (pull_request) Successful in 4s
Intégration / Aucun secret commité (pull_request) Successful in 3s
Intégration / Tableau de bord — dépendances, tests et construction (pull_request) Successful in 22s
Infra Ansible / Playbooks Ansible valides (pull_request) Successful in 1m6s
Intégration / Python — qualité, tests et dépendances (pull_request) Successful in 2m10s
87f1b47cf4
Moteur : l'alerting unifié de Grafana, pas d'Alertmanager. Cinq règles
provisionnées par fichier (grafana/provisioning/alerting/), évaluées sur
Prometheus. Canal unique : un webhook vers un petit relais qui ouvre une
issue dans la forge, assignée au destinataire nommé par la règle, et la
referme à la résolution. Réseau clos : la forge est la seule destination,
pas de relais SMTP.

Les cinq alertes : collecte arrêtée, disque bientôt plein, API source
lente ou muette (sonde blackbox), cible de supervision tombée, sauvegarde
PostgreSQL en échec. Cette dernière ferme l'écart n°4 de POSTGRESQL.md
(« aucune alerte sur échec — attend Prometheus »).

- collecte-current.sh et pg-backup.sh déposent des métriques ev_ops_*
  dans /var/lib/node_exporter/textfile, que node-exporter republie
- blackbox-exporter ajouté à la pile (127.0.0.1:9115) ; job blackbox
  dans prometheus.yml sonde l'API source, la forge et Grafana
- relais-forge : bibliothèque standard, image python montée telle quelle,
  jeton du coffre (vault_forge_alerte_token, portée « issue »)
- rôle app : création du répertoire textfile, garde du jeton dans l'assert
- test-supervision.sh : cinq règles, destinataire nommé, point de contact
  webhook, aucun jeton en clair, YAML du provisioning valide
- runbook supervision.md § 7 : tableau des cinq alertes, déclenchement
  réel pour la preuve ENF-08, réglage des seuils, pannes du relais
gabriel self-assigned this 2026-09-04 12:10:24 +00:00
lenaic requested changes 2026-09-04 13:30:52 +00:00
Dismissed
lenaic left a comment

Relu sur gabriel/42-alertes. Le fond est bon et le travail est propre : un
seul point m'empêche d'approuver
, plus deux remarques.

Ce qui est bien fait

L'écriture des métriques est atomique, avec le temporaire en .prom.$$ que
node-exporter ignore puisqu'il ne finit pas en .prom. Et la garde
[ -d ] && [ -w ] || return 0 suivie du || true met la priorité au bon
endroit : une métrique non publiée ne fait jamais échouer une relève. La
supervision n'est pas devenue une dépendance de la collecte.

La distinction entre derniere_tentative et derniere_reussite est juste, et
c'est bien la seconde qui porte l'alerte. Les deux nouvelles images sont
épinglées par empreinte. Et le relais répond toujours 200, avec la bonne raison
écrite dans le code : un 5xx ferait réémettre Grafana en boucle et rouvrirait des
issues en double.

Bloquant : l'assertion casse le déploiement entier, pas seulement l'alerting

- vault_forge_alerte_token | default('') | length > 0

Cette ligne est dans l'assertion d'entrée du rôle app. Sans le jeton, ce n'est
pas le relais qui échoue, c'est le rôle entier : collecteur, crontab,
migrations, piles. Or deploy.yml joue --tags app,proxy, donc une fusion vers
main avant la création du compte casse tout le déploiement.

Tu le signales dans la demande, donc ce n'est pas un oubli. Ce que je conteste,
c'est le choix : le rôle sait déjà faire mieux, depuis la #114.

when: item.stat.exists
loop: "{{ app_secrets_piles.results }}"

Une pile dont le secret manque est sautée bruyamment, et le reste du socle part.
Le commentaire au-dessus le dit : « le déploiement suivant la ramassera ». Cette
assertion contredit ce motif.

Et il y a une seconde incohérence, interne à ta demande : relais.py tolère
l'absence du jeton, il démarre et journalise un avertissement. Ansible refuse
donc de déployer pour un secret que le service accepte de ne pas avoir.

Concrètement : sortir le jeton de l'assertion d'entrée et traiter le relais comme
les autres piles, sauté si son secret manque. Le déploiement passe, l'alerting
attend le compte de service, et personne n'est bloqué entre-temps.

Remarque 1 : le relais n'authentifie rien

Tout ce qui atteint 127.0.0.1:9095 peut ouvrir et fermer des issues dans le
dépôt, sans secret partagé. C'est acceptable sur la boucle locale et je ne
demande pas de le changer maintenant. Mais ça mérite deux lignes dans
relais-forge/README.md comme risque assumé, d'autant que l'exécuteur partage la
machine et a la socket Docker, ce qui est le #103.

Remarque 2 : des temporaires orphelins

Si un script est tué entre l'écriture et le renommage, le .prom.$$ reste pour
toujours. Sur des mois, dans un répertoire lu à chaque scrape, ça s'accumule. Un
trap de nettoyage ou un find -mmin +60 -delete suffirait.

Et un fait, pas une remarque

Conflit sur vault.yml.example : ta clé et la mienne se croisent. Trente
secondes.

Le reste, provisioning Grafana, blackbox, extension de test-supervision.sh, ne
m'inspire rien à redire.

Relu sur `gabriel/42-alertes`. Le fond est bon et le travail est propre : **un seul point m'empêche d'approuver**, plus deux remarques. ## Ce qui est bien fait L'écriture des métriques est atomique, avec le temporaire en `.prom.$$` que node-exporter ignore puisqu'il ne finit pas en `.prom`. Et la garde `[ -d ] && [ -w ] || return 0` suivie du `|| true` met la priorité au bon endroit : **une métrique non publiée ne fait jamais échouer une relève**. La supervision n'est pas devenue une dépendance de la collecte. La distinction entre `derniere_tentative` et `derniere_reussite` est juste, et c'est bien la seconde qui porte l'alerte. Les deux nouvelles images sont épinglées par empreinte. Et le relais répond toujours 200, avec la bonne raison écrite dans le code : un 5xx ferait réémettre Grafana en boucle et rouvrirait des issues en double. ## Bloquant : l'assertion casse le déploiement entier, pas seulement l'alerting ```yaml - vault_forge_alerte_token | default('') | length > 0 ``` Cette ligne est dans l'assertion d'entrée du rôle `app`. Sans le jeton, ce n'est pas le relais qui échoue, c'est **le rôle entier** : collecteur, crontab, migrations, piles. Or `deploy.yml` joue `--tags app,proxy`, donc une fusion vers `main` avant la création du compte casse tout le déploiement. Tu le signales dans la demande, donc ce n'est pas un oubli. Ce que je conteste, c'est le choix : **le rôle sait déjà faire mieux**, depuis la #114. ```yaml when: item.stat.exists loop: "{{ app_secrets_piles.results }}" ``` Une pile dont le secret manque est sautée bruyamment, et le reste du socle part. Le commentaire au-dessus le dit : « le déploiement suivant la ramassera ». Cette assertion contredit ce motif. Et il y a une seconde incohérence, interne à ta demande : `relais.py` **tolère** l'absence du jeton, il démarre et journalise un avertissement. Ansible refuse donc de déployer pour un secret que le service accepte de ne pas avoir. Concrètement : sortir le jeton de l'assertion d'entrée et traiter le relais comme les autres piles, sauté si son secret manque. Le déploiement passe, l'alerting attend le compte de service, et personne n'est bloqué entre-temps. ## Remarque 1 : le relais n'authentifie rien Tout ce qui atteint `127.0.0.1:9095` peut ouvrir et fermer des issues dans le dépôt, sans secret partagé. C'est acceptable sur la boucle locale et je ne demande pas de le changer maintenant. Mais ça mérite deux lignes dans `relais-forge/README.md` comme risque assumé, d'autant que l'exécuteur partage la machine et a la socket Docker, ce qui est le #103. ## Remarque 2 : des temporaires orphelins Si un script est tué entre l'écriture et le renommage, le `.prom.$$` reste pour toujours. Sur des mois, dans un répertoire lu à chaque scrape, ça s'accumule. Un `trap` de nettoyage ou un `find -mmin +60 -delete` suffirait. ## Et un fait, pas une remarque Conflit sur `vault.yml.example` : ta clé et la mienne se croisent. Trente secondes. Le reste, provisioning Grafana, blackbox, extension de `test-supervision.sh`, ne m'inspire rien à redire.
supervision: corrige les points de relecture de la #42 (#152)
All checks were successful
Intégration / Contrôles statiques du dépôt (pull_request) Successful in 5s
Intégration / Aucun secret commité (pull_request) Successful in 3s
Intégration / Tableau de bord — dépendances, tests et construction (pull_request) Successful in 23s
Infra Ansible / Playbooks Ansible valides (pull_request) Successful in 1m13s
Intégration / Python — qualité, tests et dépendances (pull_request) Successful in 2m6s
0a59d46b06
- l'assertion d'entrée du rôle app ne bloque plus tout le déploiement
  pour le jeton du relais d'alerte, absent tant que le compte de
  service n'existe pas
- documente le risque d'un relais non authentifié (relais-forge/README.md)
- purge les .prom.$$ orphelins de plus d'une heure dans les deux
  scripts qui écrivent des métriques textfile
- résout le conflit sur vault.yml.example en gardant les deux clés
  (#42 et #141)
Author
Member

Merci pour la relecture. Les quatre points sont traités dans 0a59d46 :

  • Bloquant : vault_forge_alerte_token sorti de l'assertion d'entrée du rôle app. Sans jeton, les quatre piles partent quand même ; seul l'alerting attend le compte de service, cohérent avec la tolérance de relais.py lui-même.
  • Remarque 1 : section « Risque assumé » ajoutée à relais-forge/README.md sur l'absence d'authentification du webhook, avec le lien vers le #103.
  • Remarque 2 : purge des .prom.$$ de plus d'une heure ajoutée dans collecte-current.sh et pg-backup.sh, avant toute écriture.
  • Conflit vault.yml.example : les deux clés (#42 et #141) coexistent maintenant.

Ça te va pour lever le REQUEST_CHANGES ?

Merci pour la relecture. Les quatre points sont traités dans 0a59d46 : - **Bloquant** : `vault_forge_alerte_token` sorti de l'assertion d'entrée du rôle `app`. Sans jeton, les quatre piles partent quand même ; seul l'alerting attend le compte de service, cohérent avec la tolérance de `relais.py` lui-même. - **Remarque 1** : section « Risque assumé » ajoutée à `relais-forge/README.md` sur l'absence d'authentification du webhook, avec le lien vers le #103. - **Remarque 2** : purge des `.prom.$$` de plus d'une heure ajoutée dans `collecte-current.sh` et `pg-backup.sh`, avant toute écriture. - **Conflit `vault.yml.example`** : les deux clés (#42 et #141) coexistent maintenant. Ça te va pour lever le REQUEST_CHANGES ?
Sortir vault_forge_alerte_token de l'assertion d'entrée était le bon geste,
mais supervision.env.j2 l'interpole toujours sans garde et la clé n'est dans
aucun coffre : vault.yml est identique à celui de develop, develop ne
référence la variable nulle part, et le compte de service ci-alertes n'existe
pas encore.

Rejoué en local sur le gabarit réel, sans la clé :

  fatal: [localhost]: FAILED! => {"censored": "the output has been hidden
  due to the fact that 'no_log: true' was specified for this result"}
  'vault_forge_alerte_token' is undefined

La tâche « Rendre les secrets de supervision » est la dixième sur trente du
rôle app. Tout ce qui suit ne tourne pas : MinIO, le certificat TLS, les
quatre piles, l'environnement Python, la crontab, les migrations. Et comme
deploy.yml joue --tags app,proxy, c'est le déploiement continu entier.

La garde est dans le gabarit et pas dans defaults/main.yml : ansible-lint
exige le préfixe app_ pour toute variable posée dans les défauts d'un rôle
(var-naming[no-role-prefix], profil moderate), ce qui aurait fait rougir la
chaîne. Le gabarit est de toute façon l'endroit où le caractère facultatif du
jeton se lit.

Éprouvé dans les deux sens : sans la clé le rendu donne FORGE_ALERTE_TOKEN=,
avec une clé au coffre il donne sa valeur. ansible-lint passe au profil
production, tests/ci/test-supervision.sh reste vert.
Merge develop dans la branche des alertes (#42)
All checks were successful
Intégration / Contrôles statiques du dépôt (pull_request) Successful in 6s
Intégration / Aucun secret commité (pull_request) Successful in 3s
Intégration / Tableau de bord — dépendances, tests et construction (pull_request) Successful in 21s
Infra Ansible / Playbooks Ansible valides (pull_request) Successful in 1m19s
Intégration / Python — qualité, tests et dépendances (pull_request) Successful in 3m27s
41e0b097f6
Conflits résolus :
- vault.yml.example : les deux clés coexistent, comme dans 0a59d46. La note
  qui expliquait la reprise manuelle de develop tombe, develop la fournit
  maintenant nativement.
- PRD.md, ENF-08 : la ligne de develop est retenue. Celle de la branche
  annonçait les cinq alertes comme livrées alors que la demande est encore
  ouverte.

# Conflicts:
#	docs/PRD.md
#	infra/ansible/group_vars/all/vault.yml.example
Owner

Tes quatre corrections tiennent, je les ai vérifiées une par une dans 0a59d46.
La purge des temporaires est bien placée, avant toute écriture, et son motif
*.prom.[0-9]* ne peut pas attraper un .prom légitime. Le commentaire qui
remplace la ligne d'assertion explique le choix mieux que ma remarque ne le
demandait.

J'ai poussé deux commits sur ta branche plutôt que de te renvoyer un aller
retour.
Voilà ce que j'ai changé et pourquoi.

Le correctif a déplacé la panne d'une dizaine de tâches

Sortir vault_forge_alerte_token de l'assertion d'entrée était le bon geste.
Mais supervision.env.j2 l'interpole toujours sans garde, et la clé n'est dans
aucun coffre :

vault.yml chiffré      identique au bit près à celui de develop
dernier commit dessus  1b31f7f, 03/09, la pile de supervision
develop                zéro référence à vault_forge_alerte_token

Rejoué en local sur ton gabarit réel, sans la clé :

fatal: [localhost]: FAILED! => {"censored": "the output has been hidden due to
the fact that 'no_log: true' was specified for this result", "changed": false}

'vault_forge_alerte_token' is undefined

« Rendre les secrets de supervision » est la dixième tâche sur trente du
rôle app. Tout ce qui suit ne tourne pas : MinIO, le certificat TLS, les
quatre piles, l'environnement Python, la crontab, les migrations. Et comme
deploy.yml joue --tags app,proxy, c'est le déploiement continu entier.

C'est le même effet que ce que je t'avais signalé, un cran plus loin dans le
fichier. Ansible nomme quand même la variable en défaut, donc ce n'est pas
muet, mais le fail_msg qui disait quoi faire a disparu au passage.

Ce que j'ai posé

FORGE_ALERTE_TOKEN={{ vault_forge_alerte_token | default('') }}

La garde est dans le gabarit et pas dans defaults/main.yml, où je l'avais
mise d'abord. ansible-lint refuse toute variable sans le préfixe app_ dans
les défauts d'un rôle (var-naming[no-role-prefix], profil moderate), donc
cette version aurait fait rougir la chaîne. Le gabarit est de toute façon
l'endroit où le caractère facultatif du jeton se lit, à côté des trois secrets
qui, eux, restent exigés.

Éprouvé dans les deux sens : sans clé le rendu donne FORGE_ALERTE_TOKEN=,
avec une clé au coffre il donne sa valeur. Le comportement est celui que ton
commentaire promet déjà, et relais.py fait le reste.

Et j'ai fusionné develop

La demande était repassée en conflit sur vault.yml.example, le fichier que tu
venais justement de démêler, plus docs/PRD.md depuis la fusion de la #157.

  • vault.yml.example : les deux clés coexistent, comme dans ton commit. J'ai
    retiré la note qui expliquait la reprise manuelle depuis develop, elle n'a
    plus d'objet maintenant que develop la fournit.
  • PRD.md, ENF-08 : j'ai gardé la ligne de develop. La tienne annonçait les
    cinq alertes comme livrées alors que la demande est encore ouverte. À toi de
    la remettre à jour une fois fusionnée, c'est ton document.

Vérifications

ansible-lint (depuis infra/ansible)   profil production, 49 fichiers
ansible-playbook --syntax-check       bootstrap, site, restore
tests/ci/test-role-app.yml            10 ok, 0 failed
tests/ci/test-supervision.sh          tous les cas passent
ruff check / format                   services packages, propre

La demande est repassée fusionnable.

Ce qui reste, et ce n'est pas du code

Le compte de service ci-alertes et son jeton, portée issue sur
g2/enervision seulement, puis la clé dans group_vars/all/vault.yml. Tant
que ce n'est pas fait, la pile part et l'alerting se tait en le journalisant.
Rien n'est bloqué entre temps, c'est le but.

Ça te va comme ça ? Si oui je lève ma demande de modification. Si tu préfères
une autre forme pour la garde, ou que je défasse la fusion pour la refaire
toi même, dis le et je m'aligne.

Tes quatre corrections tiennent, je les ai vérifiées une par une dans `0a59d46`. La purge des temporaires est bien placée, avant toute écriture, et son motif `*.prom.[0-9]*` ne peut pas attraper un `.prom` légitime. Le commentaire qui remplace la ligne d'assertion explique le choix mieux que ma remarque ne le demandait. **J'ai poussé deux commits sur ta branche plutôt que de te renvoyer un aller retour.** Voilà ce que j'ai changé et pourquoi. ## Le correctif a déplacé la panne d'une dizaine de tâches Sortir `vault_forge_alerte_token` de l'assertion d'entrée était le bon geste. Mais `supervision.env.j2` l'interpole toujours sans garde, et la clé n'est dans aucun coffre : ``` vault.yml chiffré identique au bit près à celui de develop dernier commit dessus 1b31f7f, 03/09, la pile de supervision develop zéro référence à vault_forge_alerte_token ``` Rejoué en local sur ton gabarit réel, sans la clé : ``` fatal: [localhost]: FAILED! => {"censored": "the output has been hidden due to the fact that 'no_log: true' was specified for this result", "changed": false} 'vault_forge_alerte_token' is undefined ``` « Rendre les secrets de supervision » est la **dixième tâche sur trente** du rôle `app`. Tout ce qui suit ne tourne pas : MinIO, le certificat TLS, les quatre piles, l'environnement Python, la crontab, les migrations. Et comme `deploy.yml` joue `--tags app,proxy`, c'est le déploiement continu entier. C'est le même effet que ce que je t'avais signalé, un cran plus loin dans le fichier. Ansible nomme quand même la variable en défaut, donc ce n'est pas muet, mais le `fail_msg` qui disait quoi faire a disparu au passage. ## Ce que j'ai posé ```jinja FORGE_ALERTE_TOKEN={{ vault_forge_alerte_token | default('') }} ``` La garde est dans le gabarit et **pas** dans `defaults/main.yml`, où je l'avais mise d'abord. `ansible-lint` refuse toute variable sans le préfixe `app_` dans les défauts d'un rôle (`var-naming[no-role-prefix]`, profil `moderate`), donc cette version aurait fait rougir la chaîne. Le gabarit est de toute façon l'endroit où le caractère facultatif du jeton se lit, à côté des trois secrets qui, eux, restent exigés. Éprouvé dans les deux sens : sans clé le rendu donne `FORGE_ALERTE_TOKEN=`, avec une clé au coffre il donne sa valeur. Le comportement est celui que ton commentaire promet déjà, et `relais.py` fait le reste. ## Et j'ai fusionné develop La demande était repassée en conflit sur `vault.yml.example`, le fichier que tu venais justement de démêler, plus `docs/PRD.md` depuis la fusion de la #157. - `vault.yml.example` : les deux clés coexistent, comme dans ton commit. J'ai retiré la note qui expliquait la reprise manuelle depuis develop, elle n'a plus d'objet maintenant que develop la fournit. - `PRD.md`, ENF-08 : j'ai gardé la ligne de develop. La tienne annonçait les cinq alertes comme livrées alors que la demande est encore ouverte. À toi de la remettre à jour une fois fusionnée, c'est ton document. ## Vérifications ``` ansible-lint (depuis infra/ansible) profil production, 49 fichiers ansible-playbook --syntax-check bootstrap, site, restore tests/ci/test-role-app.yml 10 ok, 0 failed tests/ci/test-supervision.sh tous les cas passent ruff check / format services packages, propre ``` La demande est repassée fusionnable. ## Ce qui reste, et ce n'est pas du code Le compte de service `ci-alertes` et son jeton, portée `issue` sur `g2/enervision` seulement, puis la clé dans `group_vars/all/vault.yml`. Tant que ce n'est pas fait, la pile part et l'alerting se tait en le journalisant. Rien n'est bloqué entre temps, c'est le but. Ça te va comme ça ? Si oui je lève ma demande de modification. Si tu préfères une autre forme pour la garde, ou que je défasse la fusion pour la refaire toi même, dis le et je m'aligne.
Merge branch 'develop' into gabriel/42-alertes
All checks were successful
Intégration / Tableau de bord — dépendances, tests et construction (pull_request) Successful in 28s
Intégration / Contrôles statiques du dépôt (pull_request) Successful in 5s
Intégration / Aucun secret commité (pull_request) Successful in 3s
Infra Ansible / Playbooks Ansible valides (pull_request) Successful in 54s
Intégration / Python — qualité, tests et dépendances (pull_request) Successful in 3m24s
7f66c028f6
infra: le jeton du relais d'alerte entre au coffre (#42)
All checks were successful
Intégration / Contrôles statiques du dépôt (pull_request) Successful in 5s
Intégration / Aucun secret commité (pull_request) Successful in 3s
Intégration / Tableau de bord — dépendances, tests et construction (pull_request) Successful in 29s
Infra Ansible / Playbooks Ansible valides (pull_request) Successful in 1m23s
Intégration / Python — qualité, tests et dépendances (pull_request) Successful in 3m31s
874fbff643
vault_forge_alerte_token, jeton du compte de service ci-alertes, portée
write:issue. Il manquait depuis l'ouverture de la #152 : le gabarit
supervision.env.j2 l'interpole, et sa garde default('') n'existait que pour
que le rôle app ne casse pas en son absence.

Le fichier reste chiffré en AES256, seule sa taille change.
Owner

C'est en place, tout est sur ta branche.

Le compte de service

ci-alertes            créé, id 10
jeton                 relais-alerte, portée write:issue
collaborateur         g2/enervision, écriture, et ce dépôt seulement

La restriction au dépôt vient bien du compte, pas du jeton : le schéma de l'API
ne connaît que des portées par catégorie, write:issue et compagnie, sans champ
dépôt. Écrire « jeton scopé à g2/enervision » quelque part décrirait une
garantie qui n'existe pas.

Le coffre

vault_forge_alerte_token est dans group_vars/all/vault.yml, commit 874fbff.
Le fichier reste chiffré en AES256, seule sa taille change.

Ma garde default('') dans supervision.env.j2 ne se déclenchera donc plus.
Je la laisse : elle documente pourquoi ce secret est le seul du fichier à en
avoir une, et elle protège la cible neuve qui n'aurait pas encore son compte de
service.

Ce qui reste à ta main

La ligne ENF-08 du PRD, comme tu l'as dit, une fois la demande fusionnée. Et le
runbook docs/runbooks/supervision.md §7 si tu veux y noter que le compte
existe maintenant.

Je lève ma demande de modification dès que la chaîne est verte. Bon travail sur
les quatre corrections, la purge des temporaires et le commentaire de
l'assertion étaient meilleurs que ce que ma relecture demandait.

C'est en place, tout est sur ta branche. **Le compte de service** ``` ci-alertes créé, id 10 jeton relais-alerte, portée write:issue collaborateur g2/enervision, écriture, et ce dépôt seulement ``` La restriction au dépôt vient bien du compte, pas du jeton : le schéma de l'API ne connaît que des portées par catégorie, `write:issue` et compagnie, sans champ dépôt. Écrire « jeton scopé à g2/enervision » quelque part décrirait une garantie qui n'existe pas. **Le coffre** `vault_forge_alerte_token` est dans `group_vars/all/vault.yml`, commit `874fbff`. Le fichier reste chiffré en AES256, seule sa taille change. Ma garde `default('')` dans `supervision.env.j2` ne se déclenchera donc plus. Je la laisse : elle documente pourquoi ce secret est le seul du fichier à en avoir une, et elle protège la cible neuve qui n'aurait pas encore son compte de service. **Ce qui reste à ta main** La ligne ENF-08 du PRD, comme tu l'as dit, une fois la demande fusionnée. Et le runbook `docs/runbooks/supervision.md` §7 si tu veux y noter que le compte existe maintenant. Je lève ma demande de modification dès que la chaîne est verte. Bon travail sur les quatre corrections, la purge des temporaires et le commentaire de l'assertion étaient meilleurs que ce que ma relecture demandait.
lenaic approved these changes 2026-09-07 09:50:58 +00:00
Dismissed
lenaic left a comment

Cinq contrôles verts, y compris « Aucun secret commité » sur le coffre modifié.

Je lève ma demande de modification. Les quatre points de ma relecture sont
traités, le cinquième que j'avais manqué est corrigé sur ta branche, le compte
de service existe et le jeton est au coffre.

La demande est fusionnable.

Cinq contrôles verts, y compris « Aucun secret commité » sur le coffre modifié. Je lève ma demande de modification. Les quatre points de ma relecture sont traités, le cinquième que j'avais manqué est corrigé sur ta branche, le compte de service existe et le jeton est au coffre. La demande est fusionnable.
# Conflicts:
#	infra/ansible/roles/app/defaults/main.yml
#	infra/ansible/roles/app/tasks/main.yml
supervision: relais.py passe le lint, que ma refonte de chaîne lui a étendu (#42)
Some checks failed
Intégration / Contrôles statiques du dépôt (pull_request) Successful in 8s
Intégration / Workflows — lint et audit de sécurité (pull_request) Failing after 20s
Intégration / Tableau de bord — dépendances, tests et construction (pull_request) Successful in 31s
Infra Ansible / Playbooks Ansible valides (pull_request) Successful in 2m6s
Intégration / Python — qualité, tests et dépendances (pull_request) Successful in 3m52s
1c10219106
La #158 a étendu ruff à `infra`, donc à infra/compose/supervision/. relais.py
n'était couvert par personne quand il a été écrit, et l'étape Ruff échouait
maintenant sur trois points :

- EXE001, shebang sans bit exécutable. Le conteneur lance
  `python -u /app/relais.py`, le shebang était décoratif ; le fichier est
  maintenant exécutable, ce qu'il prétendait déjà être.
- BLE001 deux fois, sur les deux `except Exception`. Les deux sont délibérés
  et le code le disait déjà en commentaire : une alerte en erreur n'emporte pas
  les autres, et le relais répond 200 même si la forge est injoignable, sinon
  Grafana réémet en boucle. Les commentaires deviennent des `noqa: BLE001`
  motivés, même forme que dans moteur.py.
- Deux appels repliés par ruff format.

Aucun changement de comportement. tests/ci/test-supervision.sh reste vert, les
dix-huit cas passent.
lenaic dismissed lenaic's review 2026-09-07 12:58:48 +00:00
Reason:

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

supervision: le banc passe shellcheck, que ma refonte de chaîne lui a étendu (#42)
All checks were successful
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 18s
Infra Ansible / Playbooks Ansible valides (pull_request) Successful in 2m14s
Intégration / Python — qualité, tests et dépendances (pull_request) Successful in 3m54s
734b940019
La #158 a ajouté une étape `shellcheck .forgejo/scripts/*.sh tests/ci/*.sh`.
test-supervision.sh y échoue six fois sur SC2015, « A && B || C n'est pas un
if-then-else ».

Et shellcheck a raison sur le fond, ce n'est pas une chicane de linter : si
`ok` sortait non nul, `echec` tournerait DERRIÈRE lui et le banc annoncerait
un défaut sur un cas qui vient de passer. Les six contrôles passent en
if/else, la raison est écrite au-dessus du premier.

Aucun changement de verdict : les dix-huit cas du banc passent avant comme
après, et shellcheck est propre sur les quatorze scripts du périmètre.
Merge branch 'develop' into gabriel/42-alertes
Some checks failed
Intégration / Tableau de bord — dépendances, tests et construction (pull_request) Successful in 35s
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 25s
Intégration / Python — qualité, tests et dépendances (pull_request) Has been cancelled
Infra Ansible / Playbooks Ansible valides (pull_request) Successful in 1m59s
54f894ba31
lenaic merged commit e3ee70a67e into develop 2026-09-07 13:09:45 +00:00
lenaic deleted branch gabriel/42-alertes 2026-09-07 13:09:45 +00:00
Sign in to join this conversation.
No reviewers
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!152
No description provided.