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 <noreply@anthropic.com>
260 lines
10 KiB
Markdown
260 lines
10 KiB
Markdown
# 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 <TOKEN> par la valeur affichée :
|
|
cat > ios/App/App/CoachAuth.swift <<'EOF'
|
|
import Foundation
|
|
enum CoachAuth { static let kCoachWebToken: String = "<TOKEN>" }
|
|
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.
|