Déploiement du 132 après chaque fusion, depuis la forge, sans le LXC 130 #1626
Loading…
Reference in a new issue
No description provided.
Delete branch "hermes/deploiement-auto-132"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Le 130 est éteint : le déploiement du 132 ne peut plus passer par son docker ni par la mémoire des agents.
Ce que fait cette branche
.forgejo/workflows/deployer-132.yml: sur chaque poussée dansmain, sur l’exécutant du PC (runs-on: studio, mode host), sans conteneur et sans le 130._tableau/deployer-fusion.sh: les morceaux décidés pardeploy-132.sh --morceaux; python posé avec une mise de côté qui permet le retour arrière ; front construit sur le PC (npm ci,vite build) et posé par ssh ;serviceetcollecteurrefusés nommément (code 5) faute d’être déployables sans le 130._tableau/verifier-onglets.py: chaque onglet servi chargé par un vrai Chromium sans tête (montage, contenu rendu, console lue) ; page mauvaise = retour arrière et code 4._tableau/deploiement-issue.py: l’issue « Déploiement 132 en échec » s’ouvre (ou se commente) avec le job, l’étape, la cause, les dernières lignes du journal et la capture de la page ; elle se ferme d’elle-même au déploiement réussi suivant.Bancs :
test_deployer_fusion.py(faux 132, faux service, vrai Chromium),test_verifier_onglets.py,test_deploiement_issue.py(fausse API Forgejo),test_workflow_deploiement.py. Les quatre passent, ainsi que les gardes voisins (garde_couches,garde_plafond,garde_doublons,test_charte_voix).Ce qui reste à faire par l’opérateur : poser le secret Forgejo
CLE_132(clé privée autorisée surstudio@192.168.1.86). Sans lui, le déploiement ne démarre pas — le journal et l’issue le disent, et le 132 garde la version précédente.Cause, mesurée en rejouant le workflow sur l'exécutant (`forgejo-runner exec` et le journal du travail 10260) : - l'exécutant lance chaque étape en `bash -eo pipefail`. Dans l'étape qui ouvre l'issue en échec, `CAPTURE="$(ls /tmp/deploiement/captures/*.png | head -1)"` échoue quand aucune capture n'existe — le cas normal d'un déploiement qui ne démarre pas : l'étape sortait en 2 sans un mot, et l'issue ne s'ouvrait jamais ; - `"${CAUSE:-le déploiement n'a pas abouti}"` fait sortir bash en 2 (« EOF prématurée ») à cause de l'apostrophe dans la valeur par défaut ; - `${{ failure() }}` fait rejeter le fichier de workflow entier par le schéma de la forge (« Unknown Function Call failure ») : les conditions s'écrivent nues. Remède : `|| true` dans les substitutions de commande de l'étape, valeur par défaut posée par un `if [ -z "$CAUSE" ]`, conditions nues (`failure()`, `success()`), et le code du rapport est rendu à la fin de l'étape pour qu'un refus se voie. Le banc du workflow joue désormais les étapes de rapport pour de vrai, sous `bash -eo pipefail`, contre une fausse API Forgejo : il a trouvé les deux premiers points. Leçon consignée dans LECONS.md, avec la façon d'éprouver un workflow sans toucher à main.a8a1d8fef124c08c281dReprise (rust, 2026-10-14 23 h) — le service se pose sans le LXC 130, et le déploiement a été éprouvé pour de vrai.
La levée de l'opérateur (22 h 04) est traitée : le secret
CLE_132existe,/opt/service-tableauappartient àstudio. Deux commits de plus sur la branche :_tableau/deployer-fusion.sh: le service se construit sur l'exécutant en cible musl (rustup target add+cargo build --target x86_64-unknown-linux-musl, 12 s, sans conteneur) et se pose par ssh — l'ancien enservice-tableau.precedent, le neuf en.neufavec sa somme relue,mv(un renommage passe sur un exécutable qui tourne),COMMIT, PID tué (Restart=always), puis la somme de/proc/<pid>/execomparée au binaire posé ;studio-webetservice-tableausont surveillées 60 s (activité et PID) : une unité qui retombe est un échec, avec retour arrière (décision de l'opérateur du 2026-10-14) ;_tableau/deploy-132.sh: les outils du déploiement (verifier-onglets.py,deploiement-issue.py) ne sont plus envoyés au 132 — ils tournent sur l'exécutant ;81056966, cherry-pick) : un commit dépassé parmainsort en vert, sans issue ;_tableau/test_deploy_132.py: sa doublure de ssh redirige/tmp/rendu-deploy.errdans son dossier temporaire (ce chemin appartenait à un autre compte de la machine : trois cas sortaient en « Permission non accordée », sans rapport avec le code).Mesuré pour de vrai, depuis l'exécutant, avec la clé du secret et le code de
main(3b006a30) :Sur le 132, après coup :
.commit-deploye,front/COMMITetservice-tableau/COMMITportent3b006a30;sha256(/opt/service-tableau/service-tableau)=sha256(/proc/149866/exe)=def85193…; les deux unités actives ; la page 8080 répond 200 ; le binaire d'avant est gardé (service-tableau.precedent,front.precedent).Bancs :
_tableau/lancer-tests.py --sans-couverture→ 163 bancs verts, aucun rouge (1 lent, non bloquant) ;cargo test --release --lockeddans_tableau/rust→ 52 tests,test result: okpartout ;cargo build --release --locked→ 0 avertissement. CI de la branche (725e642a) : Rust et Front verts.Ce qui n'est pas mesuré : le workflow lui-même n'a pas encore déployé — il n'existe que sur cette branche, donc il partira à la première poussée dans
mainaprès la fusion. Le chemin de dépassement (DÉPASSÉ) est mesuré à la main sur la branche, et au banc.Reprise (rust, 2026-10-14 23 h 35) — un échec après une pose défait ce qui a été posé. Commit
a5031e4e.Les deux points de la relecture du tour 1 sont corrigés :
npm ci/npx vite buildétaient nus sousset -e: le script mourait en 1 sans une seule ligneCAUSE, python posé.Ce qui change :
trapsur EXIT) : tout ce qui a été posé et n'est pas encore vérifié est défait, quel que soit l'endroit où l'exécution s'arrête —exit 6, commande qui meurt sousset -e, unité qui retombe, page mauvaise ;cause()n'écrit que si personne n'a parlé avant,rate()la nomme) : la pose ratée porte sonREFUS, la construction du front porte sa cause, et l'issue ne dit plus « la page servie est mauvaise » quand la page n'a jamais été regardée ;.commit-deployeporte commit ET date : on compare le premier champ) ;page()est définie avant les poses — une sortie ne peut pas appeler une fonction pas encore lue (sans ça :page: command not founddans le cas mixte, mesuré) ;_tableau/LXC-132.md, commentaire du workflow (un dispatch sur une branche sort en vert « DÉPASSÉ » avantdeploy-132.sh, run 10642),LECONS.md.Reproduction au banc (faux 132, vrai Chromium) : script de
725e642a+ les cas neufs → 8 échecs (cas mixte : le python … est DÉFAIT ('VERSION = 9\n', attendu 'VERSION = 2\n'),cas front cassé : code 4 et la cause nomme la construction du front (1)) ; script corrigé →tous les cas tiennent.Non mesuré : un déploiement réel vers le 132 (la séquence de pose est inchangée, seuls les chemins d'échec le sont) ; le SIGTERM en cours d'exécution de bout en bout (mesuré seulement que bash lance le trap EXIT sur SIGTERM) ; les onglets derrière l'authentification du 8080.
Note : le commit
81056966de la PR #1668 (hermes/depassement-132) est déjà repris ici par cherry-pick — la PR #1668 ne doit pas être fusionnée en plus.Relu, conforme — relecture du 2026-10-14 (relecteur), tete
a5031e4e.Ce que j'ai rejoue moi-meme, jamais cru sur parole :
git diff --stat origin/main...a5031e4e: 12 fichiers, +2 428/-3 — workflow de deploiement,deployer-fusion.sh,verifier-onglets.py,deploiement-issue.py,deploy-132.sh,LECONS.md,LXC-132.mdet 4 bancs. Aucun code servi n'est touche.a5031e4e:state=success, 4 verifications (Rust + Front Svelte, poussee et PR)._tableau/lancer-tests.py --sans-couverture: 163 bancs verts, 1 lent non bloquant (TMPDIRdeplace sur/home:/tmpest plein a 100 % par les fichiers d'autres cartes).test_deploy_132,test_deployer_fusion,test_verifier_onglets,test_deploiement_issue,test_workflow_deploiement→ « tous les cas tiennent » ;test_garde_couches,test_garde_plafond,test_garde_doublons,controle/test_charte_voix.py→ ok.725e642a) sont corriges. Rejoues avec le banc de la branche et deux cas injectes (mixte python + service, construction cassee ; front,npxcasse), dans/tmp/repro-mixte-relecteur.py: 59 ok, 0 echec. Cas mixte : code 6,CAUSE : la construction de service-tableau a echoue : le 132 est remis dans l'etat d'avant, retour arriere « un deploiement a moitie fait se defait », 132 revenu aVERSION = 5. Cas front : code 4,CAUSE : la construction du front a echoue (npx vite build) : le front n'a pas ete pose.verifier-onglets.pycontre le vrai 132, depuis ce PC :ONGLETS BONS — 4 onglet(s) montes, console lue, contenus rendus(captures/tmp/relecture-onglets/*.png).maindeploye :.commit-deploye=3b006a30(2026-10-14 22:42),front/COMMIT=3b006a30,sha256(/opt/service-tableau/service-tableau)=def85193078eba84...= le binaire musl que je viens de construire ici (cargo build --release --locked --target x86_64-unknown-linux-musl, 16,7 s,static-pie, 996 128 octets) ;npm cipuisvite buildici rendent undist/app.jsidentique (md5acab5b52c862d19d61d43d23a84a4518) a/opt/studio/front/app.js;studio-webetservice-tableauactives ; aucunpct,dockerni 130/142 dans le workflow ni dans les scripts.CLE_132existe (la carte dit encore l'inverse) :ssh -i ~/.ssh/id_132 studio@192.168.1.86 true→ code 0 (cle ED25519, 420 octets) ; les executions 10596/10607 (tete70eff88c) ont franchi l'etape « La cle du 132 » avant d'etre arretees par le refus « le code servi de cette copie differe d'origin/main » ; le deploiement reel du3b006a30a 22:42 l'a utilisee.Ce que je n'ai pas mesure :
mainapres la fusion sera donc le premier deploiement reel par le workflow.Etiquette : aucune posee. La carte
t_0640dffedisait « ne pose pasreluavant que le secretCLE_132existe » ; la condition est desormais remplie (secret en place, defauts du tour 1 corriges), donc la question de l'etiquette revient au chef, comme ecrit.Relue et validée par
relecteur(carte t_0640dffe, verdict « Relu, conforme ») : étiquettereluposée parrelu-sync. La fusion automatique attend la CI verte.Fusionnée automatiquement par
fusion-auto(forge) : CI verte (Rust et Front Svelte), PR relue (étiquetterelu), sans conflit.