From 66d1877449e31247e20918f005c18207e0e2e038 Mon Sep 17 00:00:00 2001 From: Sylvain Bettinelli Date: Mon, 3 Aug 2026 14:31:45 +0000 Subject: [PATCH] =?UTF-8?q?docs:=20guide=20pas=20=C3=A0=20pas=20de=20la=20?= =?UTF-8?q?session=20Xcode=20(9=20=C3=A9tapes)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rassemble tout le natif accumulé depuis le TestFlight de mai en une seule procédure ordonnée par dépendances : pull, token, App Group, capabilities, target complications (facultative), build+tests device, puis distribution. Point d'arrêt explicite après l'étape 6 : l'app tourne sur l'iPhone, la publication TestFlight peut attendre un autre jour. Co-Authored-By: Claude Opus 5 --- docs/SESSION-XCODE.md | 259 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 259 insertions(+) create mode 100644 docs/SESSION-XCODE.md diff --git a/docs/SESSION-XCODE.md b/docs/SESSION-XCODE.md new file mode 100644 index 0000000..093aeb7 --- /dev/null +++ b/docs/SESSION-XCODE.md @@ -0,0 +1,259 @@ +# Session Xcode — guide pas à pas + +**Écrit le 2026-08-03 pour Sylvain, à suivre sur le Mac mini.** + +Cette session livre **tout le natif accumulé depuis le TestFlight de mai** : +login Apple/Google natif, watchOS live workout, widgets iPhone, complications +Watch, et la routine quotidienne sur la montre. + +Compte ~1 h 30 la première fois. Les étapes 1 à 6 mènent à une app qui tourne +sur ton iPhone ; les étapes 7 à 9 la publient sur TestFlight. **Tu peux +t'arrêter après l'étape 6** et publier un autre jour. + +--- + +## Avant de commencer — ce qui a changé + +Bonne nouvelle : **il n'y a presque plus de fichiers à ajouter à la main.** Les +Swift sont déjà déclarés dans les bonnes targets (commits `caeac37`, `f30cc60`). + +Une seule exception : `CoachWatchComplications.swift`, qui a besoin d'une target +qui n'existe pas encore. C'est l'étape 5 — **et elle est facultative** (elle +n'apporte que les complications sur le cadran de la montre). + +| Ce que tu vas activer | Étape | +|---|---| +| Login Apple + Google natif | rien à faire, déjà câblé | +| Live workout watchOS | rien à faire, déjà câblé | +| Routine sur la Watch | rien à faire, déjà câblé | +| Widgets iPhone (Séance du jour, Score de forme) | étapes 2-3 (App Group) | +| Complications sur le cadran Watch | étape 5 (facultative) | + +--- + +## Étape 1 — Récupérer le code + +⚠️ **Xcode doit être FERMÉ** (`Cmd+Q`, pas juste la fenêtre). Xcode réécrit le +`project.pbxproj` depuis sa mémoire ; un `git pull` fenêtre ouverte nous a déjà +bloqués deux fois. + +```bash +cd ~/coach-ios +git pull +npm install +npx cap sync ios +``` + +**Vérification** — tu dois voir `f30cc60` ou plus récent : +```bash +git log --oneline -1 +``` + +Si `npx cap sync` râle sur la version de Node : +```bash +nvm use 22 # Capacitor 8 exige Node >= 22 +``` + +## Étape 2 — Le token d'auth (à ne pas oublier) + +Le fichier `CoachAuth.swift` n'est pas versionné (il contient un secret). **Sans +lui, le projet ne compile pas.** + +```bash +ls ios/App/App/CoachAuth.swift +``` + +- **Le fichier existe** → passe à l'étape 3. +- **Il n'existe pas** → récupère le token puis crée-le : + +```bash +# le token est sur le VPS +ssh ubuntu@83.228.246.229 'grep COACH_WEB_TOKEN ~/.config/infomaniak.env' + +# puis, en remplaçant par la valeur affichée : +cat > ios/App/App/CoachAuth.swift <<'EOF' +import Foundation +enum CoachAuth { static let kCoachWebToken: String = "" } +EOF +``` + +## Étape 3 — App Group sur le portail Apple + +Nécessaire pour que les widgets lisent les données de l'app. À faire une seule +fois, dans le navigateur. + +1. [developer.apple.com](https://developer.apple.com) → **Certificates, IDs & Profiles** +2. **Identifiers** → menu déroulant en haut à droite → **App Groups** +3. Le groupe `group.ch.hypnotruck.coach` existe déjà ? → rien à faire. + Sinon : **+** → *App Group* → Description `Coach Hypnotruck`, Identifier + `group.ch.hypnotruck.coach` → **Continue** → **Register** + +## Étape 4 — Activer la capability dans Xcode + +```bash +open ios/App/App.xcworkspace +``` + +Pour **chacune** de ces trois targets (colonne de gauche → projet **App** → +onglet **TARGETS**) : + +| Target | Capability à ajouter | +|---|---| +| **App** | App Groups | +| **CoachLiveActivity** | App Groups | +| **CoachWatch** | App Groups | + +Pour chaque target : onglet **Signing & Capabilities** → **+ Capability** (en +haut à gauche) → tape « App Groups » → double-clic → **coche** +`group.ch.hypnotruck.coach` dans la liste qui apparaît. + +> Si le groupe n'apparaît pas dans la liste, clique sur le bouton **refresh** +> sous la liste, ou re-connecte ton compte (Xcode → Settings → Accounts). + +⚠️ **Dès que c'est fait, commit + push** — sinon ton prochain `git pull` sera +bloqué par les modifications locales : + +```bash +git add -A ios/App && git commit -m "chore(xcode): App Groups sur App, LiveActivity et Watch" && git push +``` + +## Étape 5 — Complications Watch *(facultative, ~15 min)* + +**Tu peux sauter cette étape** et y revenir plus tard : tout le reste fonctionne +sans. Elle n'ajoute que les complications sur le cadran de la montre. + +1. Menu **File → New → Target…** +2. Onglet **watchOS** → **Widget Extension** → **Next** +3. Product Name : `CoachWatchWidgets` — décoche *Include Live Activity* — + **Embed in Application** : `CoachWatch` → **Finish** +4. Xcode propose d'activer le nouveau schéma → **Activate** +5. Dans le dossier `CoachWatchWidgets` créé, **supprime** le fichier + `CoachWatchWidgets.swift` généré (clic droit → Delete → *Move to Trash*) +6. Clic droit sur le dossier `CoachWatchWidgets` → **Add Files to "App"…** → + sélectionne `ios/App/CoachWatchWidgets/CoachWatchComplications.swift` → + **décoche** *Copy items if needed*, **coche** la target `CoachWatchWidgets` +7. Sélectionne `CoachWidgetSnapshot.swift` dans la colonne de gauche → + inspecteur de droite (`Cmd+Option+1`) → **Target Membership** → coche + **CoachWatchWidgets** +8. Target `CoachWatchWidgets` → **Signing & Capabilities** → **+ Capability** → + **App Groups** → coche `group.ch.hypnotruck.coach` + +Puis commit + push (même raison qu'à l'étape 4). + +## Étape 6 — Compiler et tester sur l'iPhone + +1. Branche l'iPhone, déverrouille-le, avec l'Apple Watch au poignet et appairée +2. En haut de Xcode, sélectionne le schéma **App** et ton iPhone comme device +3. **Product → Clean Build Folder** (`Cmd+Shift+K`) +4. **Run** (`Cmd+R`) + +### Si ça ne compile pas + +| Erreur | Cause | Solution | +|---|---|---| +| `cannot find 'CoachAuth' in scope` | étape 2 sautée | crée `CoachAuth.swift` | +| `no such module 'Capacitor'` | sync manquant | `npx cap sync ios`, Xcode fermé | +| erreur de signing | profil pas régénéré | Signing & Capabilities → décoche/recoche *Automatically manage signing* | +| `CoachWidgetStore` introuvable | Target Membership | vérifie que `CoachWidgetSnapshot.swift` est coché pour la target qui râle | + +### Tests, dans l'ordre (5 min) + +1. **L'app se lance et tu es connecté** → le cookie natif fonctionne. +2. **Live workout** (le seul flux déjà validé, à ne pas casser) : démarre une + séance sur la Watch → la FC doit apparaître sur `/live` de l'iPhone. + ⚠️ *C'est le test le plus important : j'ai touché à `CoachLiveBridge` pour + faire passer la routine. Si la FC ne remonte plus, dis-le-moi.* +3. **Routine sur la Watch** : ouvre `/routine` sur l'iPhone (ça pousse les blocs + vers la montre) → app Coach sur la Watch → **Routine du jour** → les 6 blocs + s'affichent → coche-en un → la page iPhone se met à jour **sans recharger**. +4. **Widgets iPhone** : écran d'accueil → appui long → **+** → cherche *Coach* → + ajoute « Séance du jour » et « Score de forme ». +5. **Login natif** : déconnecte-toi, teste *Se connecter avec Apple* et *Google*. + +Vérification serveur de la routine : +```bash +ssh ubuntu@83.228.246.229 'cat /home/ubuntu/coach_sportif/data/routine_log.json' +``` + +**Si tu t'arrêtes ici, c'est déjà un succès** : ton iPhone a tout le natif. + +--- + +## Étape 7 — Préparer la distribution + +Deux réglages avant d'archiver. + +**a. Numéro de build** — target **App** → onglet **General** : +`Version` = `1.3`, `Build` = `23` (le repo est à 1.2 / 22). + +**b. Push notifications en production** — `ios/App/App/App.entitlements` +contient `aps-environment = development`. En TestFlight, les notifications push +distantes ne marcheront pas avec cette valeur. + +Le plus simple : laisse Xcode gérer. Avec *Automatically manage signing*, le +profil de distribution force `production` à l'archivage. **Vérifie-le après +l'étape 8** : Organizer → clic droit sur l'archive → *Show in Finder* → clic +droit → *Afficher le contenu* → `Products/Applications/App.app` → clic droit → +*Afficher le contenu* → ouvre `embedded.mobileprovision` avec TextEdit → cherche +`aps-environment`, il doit valoir `production`. + +Si ce n'est pas le cas, édite `App.entitlements` en mettant `production`, +ré-archive, et **remets `development`** ensuite pour ne pas casser tes builds de +dev. + +## Étape 8 — Archiver + +1. En haut, remplace ton iPhone par **Any iOS Device (arm64)** +2. **Product → Archive** (compte 5-10 min) +3. La fenêtre **Organizer** s'ouvre sur l'archive + +Si *Archive* est grisé : tu es encore sur un simulateur, repasse en *Any iOS Device*. + +## Étape 9 — Envoyer sur TestFlight + +1. Dans l'Organizer : **Distribute App** → **App Store Connect** → **Upload** +2. Laisse les options par défaut → **Next** → **Upload** +3. Attends 5-30 min qu'Apple finisse le *processing* (mail de confirmation) +4. [appstoreconnect.apple.com](https://appstoreconnect.apple.com) → **Coach + Hypnotruck** → **TestFlight** → le build 23 apparaît +5. ⚠️ **Assigne le build au groupe de testeurs internes** — sans ça, il + n'apparaît pas dans TestFlight sur ton iPhone. Ça nous a bloqués en mai : + *Internal Testing* → ton groupe → **+** → coche le build 23 +6. Sur l'iPhone : app **TestFlight** → **Mettre à jour** + +⚠️ Le cache WKWebView est tenace. Si l'app affiche encore l'ancienne interface +après mise à jour : **désinstalle l'app** puis réinstalle depuis TestFlight. + +--- + +## En cas de blocage + +Note l'étape et le message d'erreur exact, et envoie-les-moi. Utile à joindre : + +```bash +# état du repo +cd ~/coach-ios && git log --oneline -3 && git status -sb + +# les fichiers Swift sont-ils tous câblés ? (doit ne rien afficher sauf +# CoachWatchComplications si tu as sauté l'étape 5) +for f in $(find ios -name '*.swift' -not -path '*/CapApp-SPM/*'); do + grep -q "$(basename $f)" ios/App/App.xcodeproj/project.pbxproj || echo "NON CÂBLÉ: $f" +done +``` + +Pour les erreurs de plugins à l'exécution : Safari → menu **Développement** → +ton iPhone → `coach.hypnotruck.ch` → console : +```js +Object.keys(Capacitor.Plugins).filter(k => k.startsWith('Coach')) +// doit lister : CoachWorkoutKit, CoachHealthRoute, CoachWorkoutObserver, +// CoachLiveBridge, CoachAppleAuth, CoachGoogleAuth, +// CoachWidgetBridge, CoachRoutineBridge +``` + +## Rappels permanents + +- **Toujours quitter Xcode avant un `git pull`.** +- **Toujours commit + push après une modification faite dans Xcode** + (capability, signing, target) — sinon le prochain pull est bloqué. +- Les changements **web** (templates, CSS, routes) ne demandent **aucun build** : + ils arrivent au prochain lancement de l'app.