From af84b21f898ab05a906aaf441ae2d24e13ae593c Mon Sep 17 00:00:00 2001 From: Claude Code DTP Worker Date: Mon, 3 Aug 2026 03:46:18 +0000 Subject: [PATCH] =?UTF-8?q?[DTP-Worker=2020260803=5F033642]=20Sprint=205?= =?UTF-8?q?=20P1=20=C2=B7=20feat=20=C2=B7=20CI/CD=20Mobile=20:=20workflow?= =?UTF-8?q?=20Gitea=20Actions=20mobile-build.yml=20(build=20EAS=20iOS=20Ap?= =?UTF-8?q?p=20Store=20#32=20+=20Android=20Play=20Store)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Livrable FONCTIONNEL non fait, explicitement demandé par DIRECTIVE_MOBILE_STORES _20260803.md P1 (« Créer .gitea/workflows/mobile-build.yml ») — classé non-bloqueur in-périmètre worker. Triggers push main + tags v* + workflow_dispatch ; jobs preflight (toujours vert) + build-ios + build-android → eas build --profile production --non-interactive (profils lus de mobile/app_config/out/eas_build.json). Activation différée (#6/#8) : builds gardés par `if secrets.EAS_TOKEN != '' && vars.MOBILE_NATIVE_REPO != ''` → SKIP tant que Michel n'a pas fourni token+repo natif → CI jamais rouge avant activation ; aucun credential fabriqué (a_confirmer). Code Expo natif = autre dépôt Gitea, cloné au run (jamais recopié). Gitea only (#2). Consommateur régénéré : pointeur README mobile (4261→4917 o) mesuré par critère DOC de l'audit 4Big → audit_4big_gen.py build régénéré (verdict inchangé 22/22 ≥95). check_ci_integrity n'inspecte que ci.yml → 2e workflow invisible au gate. Zéro nouveau module · zéro gate ajouté (#5). run_ci.sh 30 PASS · 0 FAIL. Co-Authored-By: Claude Opus 4.8 (1M context) --- .gitea/workflows/mobile-build.yml | 135 ++++++++++++++++++ 05_activity_log/2026-08-03.md | 50 +++++++ .../mobile/app_config/README.md | 8 ++ .../qa/audit_4big/out/quality_report.json | 2 +- 4 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 .gitea/workflows/mobile-build.yml diff --git a/.gitea/workflows/mobile-build.yml b/.gitea/workflows/mobile-build.yml new file mode 100644 index 0000000..847780e --- /dev/null +++ b/.gitea/workflows/mobile-build.yml @@ -0,0 +1,135 @@ +# ============================================================================ +# Mobile Build (EAS) · OTO Enterprise OS DTP · Gitea Actions +# ---------------------------------------------------------------------------- +# Roadmap Sprint 5 l.56-57 « Mobile : Rebuild Expo 54 + submit App Store #32 + +# Play Store » · DIRECTIVE_MOBILE_STORES_20260803.md · P1 « CI/CD Mobile ». +# +# Plateforme : Gitea Actions UNIQUEMENT (CLAUDE.md #2 · JAMAIS GitHub). +# Runner : act_runner enregistré sur le VPS avec le label « ubuntu-latest » +# (même runner que ci.yml · voir ci/README.md). +# +# PÉRIMÈTRE (#8). Ce worker versionne la CONFIG CI/CD ; l'exécution `eas build` / +# `eas submit` a lieu HORS repo (service EAS / stores), pilotée par l'agent +# Mobile. La config des profils de build est la source de vérité versionnée +# 05_deliverables_mvp/mobile/app_config/out/eas_build.json (profils development / +# preview / production) — ce workflow ne fait que l'invoquer. +# +# CODE APP HORS REPO. Le code natif Expo vit dans un AUTRE dépôt Gitea +# (/opt/oto/mobile/native/ · Expo SDK 51 actuel → cible Expo 54, roadmap l.56). +# Il est cloné au run depuis ${{ vars.MOBILE_NATIVE_REPO }} — jamais recopié ici. +# +# ACTIVATION DIFFÉRÉE (#6 · zéro credential inventé). Tant que le secret +# EAS_TOKEN n'est pas fourni par Michel (expo.dev · 2 min · cf. directive +# « Vrais bloqueurs »), les jobs de build sont SKIP — donc ce workflow ne rend +# JAMAIS le CI rouge avant que Michel n'active. Le job `preflight` reste vert et +# rapporte l'état des secrets à fournir. Rien n'est fabriqué : tout identifiant +# (repo natif, token, credentials Apple/Google) est un secret/variable +# `a_confirmer`, cohérent avec les champs `null · a_confirmer` du livrable mobile. +# ============================================================================ +name: Mobile Build (EAS) + +on: + # Conforme directive P1 : « Trigger sur push branche main ou tag v* ». + push: + branches: [main] + tags: ['v*'] + paths: + - '05_deliverables_mvp/mobile/**' + - '.gitea/workflows/mobile-build.yml' + workflow_dispatch: + inputs: + platform: + description: 'Plateforme à builder' + required: true + default: 'all' + type: choice + options: [all, ios, android] + profile: + description: 'Profil EAS (cf. eas_build.json)' + required: true + default: 'production' + type: choice + options: [production, preview, development] + +# Un seul build mobile à la fois par ref (annule le précédent en cours). +concurrency: + group: mobile-build-${{ github.ref }} + cancel-in-progress: true + +env: + # Profil par défaut (aligné directive P4 : builds `--profile production`). + EAS_PROFILE: ${{ github.event.inputs.profile || 'production' }} + # Config des profils versionnée par le worker (source de vérité). + EAS_CONFIG: 05_deliverables_mvp/mobile/app_config/out/eas_build.json + +jobs: + # -------------------------------------------------------------------------- + # Préflight : TOUJOURS vert. Prouve que la config EAS versionnée est présente + # et rapporte l'état des secrets requis, SANS jamais échouer avant activation. + # -------------------------------------------------------------------------- + preflight: + name: Préflight config EAS + état secrets + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Config EAS versionnée présente (eas_build.json) + run: test -f "$EAS_CONFIG" && echo "OK · profils build/submit versionnés dans $EAS_CONFIG" + - name: État des secrets requis (aucun secret n'est loggé) + run: | + echo "Profil sélectionné : $EAS_PROFILE" + if [ -n "${{ secrets.EAS_TOKEN }}" ]; then + echo "EAS_TOKEN : présent → les jobs de build vont s'exécuter." + else + echo "EAS_TOKEN : ABSENT → jobs de build SKIP (attente Michel · expo.dev)." + fi + [ -n "${{ vars.MOBILE_NATIVE_REPO }}" ] && echo "MOBILE_NATIVE_REPO: configuré." || echo "MOBILE_NATIVE_REPO: a_confirmer (dépôt Gitea du code natif Expo)." + + # -------------------------------------------------------------------------- + # Build iOS · SKIP tant que EAS_TOKEN absent (activation Michel · #6/#8). + # App Store #32 · `eas build --platform ios --profile production`. + # -------------------------------------------------------------------------- + build-ios: + name: EAS build iOS (App Store #32) + runs-on: ubuntu-latest + needs: preflight + if: ${{ secrets.EAS_TOKEN != '' && vars.MOBILE_NATIVE_REPO != '' && (github.event.inputs.platform == 'all' || github.event.inputs.platform == 'ios' || github.event_name != 'workflow_dispatch') }} + env: + EXPO_TOKEN: ${{ secrets.EAS_TOKEN }} + steps: + - name: Cloner le code natif Expo (dépôt Gitea séparé) + uses: actions/checkout@v4 + with: + repository: ${{ vars.MOBILE_NATIVE_REPO }} + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: '20' + - name: Installer EAS CLI + run: npm install -g eas-cli + - name: EAS build iOS (production · non-interactive) + run: eas build --platform ios --profile "$EAS_PROFILE" --non-interactive --no-wait + + # -------------------------------------------------------------------------- + # Build Android · SKIP tant que EAS_TOKEN absent (activation Michel · #6/#8). + # Play Store · `eas build --platform android --profile production`. + # -------------------------------------------------------------------------- + build-android: + name: EAS build Android (Play Store) + runs-on: ubuntu-latest + needs: preflight + if: ${{ secrets.EAS_TOKEN != '' && vars.MOBILE_NATIVE_REPO != '' && (github.event.inputs.platform == 'all' || github.event.inputs.platform == 'android' || github.event_name != 'workflow_dispatch') }} + env: + EXPO_TOKEN: ${{ secrets.EAS_TOKEN }} + steps: + - name: Cloner le code natif Expo (dépôt Gitea séparé) + uses: actions/checkout@v4 + with: + repository: ${{ vars.MOBILE_NATIVE_REPO }} + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: '20' + - name: Installer EAS CLI + run: npm install -g eas-cli + - name: EAS build Android (production · non-interactive) + run: eas build --platform android --profile "$EAS_PROFILE" --non-interactive --no-wait diff --git a/05_activity_log/2026-08-03.md b/05_activity_log/2026-08-03.md index 267afbd..3c645b4 100644 --- a/05_activity_log/2026-08-03.md +++ b/05_activity_log/2026-08-03.md @@ -1,5 +1,55 @@ # Activity Log · 2026-08-03 · Claude Code DTP Worker +## Session 033642 · Sprint 5 P1 · Livrable FONCTIONNEL : workflow CI/CD Mobile `.gitea/workflows/mobile-build.yml` (build EAS iOS + Android) + +**Contexte + choix de tâche.** `./run_ci.sh` au démarrage : **30 PASS · 0 FAIL · 0 SKIP**, +arbre propre. Michel : « commits fonctionnels, pas juste docs ». La roadmap est couverte +par des modules gatés+verts, mais `DIRECTIVE_MOBILE_STORES_20260803.md` (Sprint 5, actif) +liste explicitement en **P1 · CI/CD Mobile** la création de `.gitea/workflows/mobile-build.yml` +— classée **non-bloqueur** (« configurer sans token, activation quand Michel fournit »), +donc **in-périmètre worker** (fichier config versionné, aucune exécution VPS/stores #8). +Vérifié absent : `.gitea/workflows/` ne contenait que `ci.yml`. **Vraie tâche fonctionnelle +non faite** → exécutée. + +**Livrable créé : `.gitea/workflows/mobile-build.yml`.** +- **Triggers** (conformes directive P1) : push `main` + tags `v*` (paths `mobile/**` + + le workflow) + `workflow_dispatch` (inputs `platform` all/ios/android, `profile`). +- **Jobs** : `preflight` (TOUJOURS vert · prouve la présence de la config EAS versionnée + `mobile/app_config/out/eas_build.json` + rapporte l'état des secrets, sans jamais les + logger) ; `build-ios` (App Store #32) + `build-android` (Play Store) → `eas build + --platform … --profile production --non-interactive` (directive P4). +- **Source de vérité** : les profils de build viennent de l'artefact versionné + `eas_build.json` (development/preview/production) — pas réinventés. +- **Code natif hors repo** : le code Expo vit dans un **autre dépôt Gitea** + (`/opt/oto/mobile/native/` · Expo 51→cible 54) ; cloné au run depuis la variable + `vars.MOBILE_NATIVE_REPO` — **jamais recopié ici**. + +**Sûreté (activation différée · #6 zéro invention · #8).** Les jobs de build sont gardés +par `if: secrets.EAS_TOKEN != '' && vars.MOBILE_NATIVE_REPO != ''` → **SKIP** tant que +Michel n'a pas fourni token+repo (« Vrais bloqueurs » de la directive : EAS_TOKEN 2 min sur +expo.dev). Conséquence : ce workflow **ne rend JAMAIS le CI rouge** avant activation, et +`preflight` reste vert et informatif. Aucun credential fabriqué : token, repo natif, +appleId/ascAppId/serviceAccount restent des secrets/vars `a_confirmer` — cohérent avec les +champs `null · a_confirmer` du livrable mobile. Plateforme **Gitea Actions uniquement** (#2). + +**Non-régression des gates (vérifié).** `check_ci_integrity.sh` n'inspecte QUE `ci.yml` +(chemin en dur `CI=".gitea/workflows/ci.yml"`) → le 2e workflow lui est invisible, aucun +job à ajouter à `gate.needs`. `guard_constraints.sh` vert (aucune URL/usage interdit ; +`actions/checkout@v4` déjà toléré via `ci.yml`). YAML valide (pyyaml). + +**Consommateur régénéré (classe [[artifact-reproducibility-gate]]).** Ajout d'un pointeur +concis (paragraphe « CI/CD Mobile » + 1 ligne au tableau périmètre) dans +`mobile/app_config/README.md` → sa taille passe 4261→4917 octets, mesurée par le critère +**DOC** de l'audit 4Big. `check-artifacts` a viré ROUGE (dérive attendue) → +`audit_4big_gen.py build -o out` régénéré : **seule** la ligne `evidence "README.md (…octets)"` +change ; verdict inchangé **PASS · 22/22 modules ≥ 95**. Lien Markdown vérifié résolvant +(`../../../.gitea/workflows/mobile-build.yml`). + +**Vérifications finales.** `./run_ci.sh` → **30 PASS · 0 FAIL · 0 SKIP**. **Zéro nouveau +module · zéro gate ajouté (#5)** · aucune commande VPS (#8). +Aucun `git clean` exécuté . + + ## Session 020634 · Dérive ground-truth résiduelle : roadmap L18 (colonne « Existe déjà ») affirmait encore « Expo 54 » — corrigée → Expo 51 réel (#6) **Contexte.** `./run_ci.sh` au démarrage : **30 PASS · 0 FAIL · 0 SKIP**, arbre propre. diff --git a/05_deliverables_mvp/mobile/app_config/README.md b/05_deliverables_mvp/mobile/app_config/README.md index 0798ca3..7b47ab6 100644 --- a/05_deliverables_mvp/mobile/app_config/README.md +++ b/05_deliverables_mvp/mobile/app_config/README.md @@ -19,6 +19,14 @@ produit uniquement la **config** que l'agent Mobile consomme sur le poste/CI EAS | `app.config` Expo (thème, locales, navigation) | `eas build` (Expo 54) | | `eas.json` (profils build/submit) | `eas submit` App Store #32 / Play Store | | navigation par rôle (gating RBAC) | credentials / signing / assets binaires | +| workflow CI/CD `.gitea/workflows/mobile-build.yml` (Sprint 5 P1) | exécution `eas build` sur runner EAS | + +**CI/CD Mobile (Sprint 5 P1 · directive `DIRECTIVE_MOBILE_STORES_20260803.md`).** Le +workflow Gitea Actions [`.gitea/workflows/mobile-build.yml`](../../../.gitea/workflows/mobile-build.yml) +invoque `eas build` iOS + Android (profil `production`) depuis les profils versionnés +d'`out/eas_build.json`. Il est **désactivé sans effet** (jobs de build SKIP · CI jamais +rouge) tant que Michel n'a pas fourni le secret `EAS_TOKEN` et la variable +`MOBILE_NATIVE_REPO` (dépôt Gitea du code natif Expo) — aucun credential n'est fabriqué (#6/#8). ## Zéro invention (#6) diff --git a/05_deliverables_mvp/qa/audit_4big/out/quality_report.json b/05_deliverables_mvp/qa/audit_4big/out/quality_report.json index 6fe91df..3797844 100644 --- a/05_deliverables_mvp/qa/audit_4big/out/quality_report.json +++ b/05_deliverables_mvp/qa/audit_4big/out/quality_report.json @@ -606,7 +606,7 @@ "criterion": "DOC", "weight": 20, "passed": true, - "evidence": "README.md (4261 octets)" + "evidence": "README.md (4917 octets)" }, { "criterion": "CONTRAT",