[DTP-Worker 20260805_001109] Nouveau gate check-mobile-workflow : la structure de mobile-build.yml devient opposable au merge (surface mutation-testée UNGATED, 1re couverture) → 32→33 jobs
- ci/check_mobile_workflow.sh (8e gate statique) · 4 invariants lus dans le fichier (#6) : MOB-1 bien-formé (YAML strict si PyYAML) · MOB-2 aucun secrets. en if: de job (portabilité act/Gitea, verrouille le correctif 234104) · MOB-3 builds gatés sur needs.preflight.outputs.has_token (activation différée #6/#8) · MOB-4 contrat outputs (déclarés==référencés==alimentés, 0 dangling). - Preuve UNGATED avant ajout : réintroduire secrets. en if: de job → 7/7 gates statiques verts. - Gate mutation-testé : 5 mutations toutes ROUGES, fichier propre re-VERT. - Câblé dans ci.yml + gate.needs ; check-ci-integrity INV-A/B verts ; run_ci auto → 33 PASS. - ci/README.md : ligne §1 + détail §2 + nuance « Second workflow ». - 0 nouveau module · 0 chiffre inventé · 0 edition prod hors CI · aucune commande VPS. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
# Activity Log · 2026-08-05 · Claude Code DTP Worker
|
||||
|
||||
## Session 001109 · Nouveau gate `check-mobile-workflow` — la structure de `mobile-build.yml` devient opposable au merge (surface mutation-testée UNGATED, 1er contrôle) → 1 gate ajouté + câblé · 32→33 jobs
|
||||
|
||||
**Contexte + choix de tâche.** `./run_ci.sh` au démarrage : **32 PASS · 0 FAIL · 0
|
||||
SKIP**, arbre propre. Roadmap `ROADMAP_8_WEEKS_OR_LESS.md` intégralement livrée/gatée
|
||||
(8 sprints). Les 4 sessions du 08-04 (`221055`, `224101`, `231101`, `234104`) avaient
|
||||
saturé les surfaces d'audit read-only (inter-artefacts, dérive non-gatée, attestation
|
||||
stakeholder) puis **durci `mobile-build.yml`** (pattern preflight-output, portable
|
||||
GitHub/Gitea). Cette dernière édition a laissé une **queue** : son propre log notait
|
||||
« Aucun gate ne linte la structure de `mobile-build.yml` (`check-ci-integrity` ne
|
||||
verrouille QUE `ci.yml`) ». Autrement dit le correctif de portabilité qu'elle venait
|
||||
de poser **pouvait régresser en silence** — exactement la classe « marche dans ma
|
||||
tête, casse le jour où on en a besoin » (mémoire [[mobile-build-secrets-if-gating]] :
|
||||
« workflow HORS `gate.needs` → `run_ci` won't catch a regression »). La valeur honnête
|
||||
du jour : **fermer cette queue** en rendant la structure de `mobile-build.yml`
|
||||
opposable au merge. NON redondant (#5) : c'est le **premier** contrôle de ce fichier.
|
||||
|
||||
**Preuve d'absence de couverture AVANT d'ajouter le gate** (discipline
|
||||
[[verify-uncovered-before-gating]]). Mutation : réintroduire l'exact anti-pattern
|
||||
corrigé en `234104` — `secrets.EAS_TOKEN != ''` dans un `if:` au niveau job. Résultat :
|
||||
**7/7 gates statiques restent VERTS**. Surface confirmée non gatée (ni
|
||||
`check_ci_integrity` — scope `CI=ci.yml` — ni `validate_json` — scope `.json`). Fichier
|
||||
byte-restauré aussitôt (`cp` depuis backup tmp · jamais `git clean`). <!-- ci-allow : mention de l'interdit, jamais exécuté -->
|
||||
|
||||
**Livrable : `ci/check_mobile_workflow.sh` (8ᵉ gate statique) + câblage.** Le gate lit
|
||||
des **FAITS dans le fichier** (jamais une liste à la main · #6), 4 invariants :
|
||||
- **MOB-1 · bien-formé** — existe · `name:`/`on:`/`jobs:` + 3 jobs (`preflight`,
|
||||
`build-ios`, `build-android`) ; parse YAML strict **exigé si PyYAML dispo**, sinon
|
||||
awk seul (runner sans pip → best-effort, jamais un faux vert : MOB-2/3/4 en sont
|
||||
indépendants).
|
||||
- **MOB-2 · portabilité** — **0** `secrets.` dans un `if:` de **job** (`^ if:`).
|
||||
Le contexte `secrets` n'est pas exposé dans `jobs.<id>.if` (table d'availability
|
||||
GitHub Actions) → sur `act`/Gitea il s'évaluerait vide → **SKIP silencieux**. C'est
|
||||
la régression `234104` verrouillée.
|
||||
- **MOB-3 · activation différée (#6/#8)** — chaque job de build (`run: eas build`) est
|
||||
gaté sur `needs.preflight.outputs.has_token` → SKIP tant que le token absent, donc
|
||||
le workflow ne rend jamais le CI rouge avant activation Michel.
|
||||
- **MOB-4 · contrat d'outputs** — `preflight` déclare `has_token`/`has_repo`, chaque
|
||||
`needs.preflight.outputs.<X>` référencé est **déclaré** (0 dangling) et chaque output
|
||||
déclaré est **alimenté** par un `echo …>>$GITHUB_OUTPUT`.
|
||||
|
||||
**Bug corrigé pendant l'écriture (auto-vérification).** 1er jet : `preflight` était
|
||||
classé « job de build » car un **commentaire** `# … eas build …` (l.108, entre deux
|
||||
jobs) était attribué au job précédent par le parseur awk. Corrigé en exigeant
|
||||
`run:[[:space:]]*eas build` (commande réelle, pas une mention). Après correctif : gate
|
||||
**VERT** sur le fichier propre.
|
||||
|
||||
**Mutation-testing du gate lui-même (5 mutations · toutes ROUGES, fichier propre
|
||||
re-VERT).** (1) YAML cassé (indent) · (2) `secrets.` en `if:` de job · (3) `if:` du
|
||||
job `build-ios` supprimé · (4) output fantôme référencé (`has_tokenX`) · (5) output
|
||||
`has_repo` non alimenté. Chaque mutation → `exit 1` ; `cp` backup → gate re-VERT.
|
||||
|
||||
**Câblage (garde `check-ci-integrity` INV-A/B vert).** Job `check-mobile-workflow`
|
||||
ajouté à `ci.yml` (steps `bash ci/check_mobile_workflow.sh`) **et** à `gate.needs`.
|
||||
`check_ci_integrity` reconnaît le nouveau `ci/*.sh` comme **câblé** (lancé par un job
|
||||
du gate + il source `lib.sh`) → INV-A (gate.needs == tous jobs non-manuels) et INV-B
|
||||
(tout `ci/*.sh` câblé) **restent verts**. `run_ci.sh` (dérivé de `gate.needs`, sans
|
||||
liste en dur) l'inclut **automatiquement** → passage **32→33 jobs (8 gates statiques
|
||||
+ 25 suites)**, zéro édition de `run_ci.sh` (#6, exactitude structurelle).
|
||||
|
||||
**Doc (traçabilité, pas de dérive).** `ci/README.md` : ligne §1 pour
|
||||
`check-mobile-workflow`, sous-section §2 détaillée (4 invariants + les 5 mutations),
|
||||
et nuance ajoutée à « Second workflow » (les **jobs** restent hors gate de merge, mais
|
||||
la **structure du fichier** est désormais gatée). Convention [[ci-readme-table-detail-in-section2]]
|
||||
respectée : ligne §1 courte, détail en §2. Les mentions historiques « 7 gates
|
||||
re-verts » (§2, records de mutations passées) restent exactes en **passé** ; le nouveau
|
||||
record dit **8ᵉ gate**.
|
||||
|
||||
**Vérifications.** `bash ci/check_mobile_workflow.sh` → VERT (4 invariants) ; 5
|
||||
mutations → ROUGE ; `python3 yaml.safe_load` sur `ci.yml` → valide ; `check_ci_integrity`
|
||||
→ VERT (câblage intègre) ; `./run_ci.sh` → **33 PASS · 0 FAIL · 0 SKIP**. **1 gate
|
||||
ajouté (NON redondant : 1re couverture d'un fichier mutation-testé ungated · pas un
|
||||
doublon #5) · 1 job CI câblé · 0 nouveau module · 0 chiffre inventé (#6) · 0 édition
|
||||
de production hors CI · aucune commande VPS (#8) · aucun `git clean`.** <!-- ci-allow : mention de l'interdit, jamais exécuté -->
|
||||
Reference in New Issue
Block a user