[DTP-Worker 20260803_033642] Sprint 5 P1 · feat · CI/CD Mobile : workflow Gitea Actions mobile-build.yml (build EAS iOS App Store #32 + Android Play Store)

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) <noreply@anthropic.com>
This commit is contained in:
Claude Code DTP Worker
2026-08-03 03:46:18 +00:00
parent d0b354f81e
commit af84b21f89
4 changed files with 194 additions and 1 deletions
+135
View File
@@ -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
+50
View File
@@ -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é <!-- ci-allow : mention de l'interdit absolu, jamais 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.
@@ -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)
@@ -606,7 +606,7 @@
"criterion": "DOC",
"weight": 20,
"passed": true,
"evidence": "README.md (4261 octets)"
"evidence": "README.md (4917 octets)"
},
{
"criterion": "CONTRAT",