Ce qu'il faut retenir d'abord
- Le problème n'est pas uniquement xcodebuild : cycle de vie des caches et de la machine compte davantage.
- GitHub-hosted repart à froid, un runner auto-hébergé garde mieux un état chaud.
- La persistance DerivedData + CocoaPods enlève souvent la plus grosse part du temps perdu.
- La pression disque et le bootstrap signing se déguisent en lenteur de compilation.
- Pour Flutter iOS, commencez par louer un Mac 48 h pour profiler, puis passez en runner auto-hébergé mensuel.
Mac local vs GitHub Actions : d'où viennent les minutes en plus
En local, la plupart des équipes comparent dans ce contexte :
- Local : SSD persistant + dépendances chaudes ; CI : VM éphémère + graphe froid.
- Local : même trousseau/signature ; CI : bootstrap keychain à chaque exécution.
- Local : builds répétés sur la même machine ; CI : plus de miss cache inter-branches.
En CI, le pipeline fait généralement l'inverse :
- Checkout sur un workspace propre à chaque run.
flutter build ipaouxcodebuild archiveen Release.- Sur runner hébergé, les caches ne tiennent pas — redémarrage à froid.
Beaucoup d'équipes comparent seulement `xcodebuild archive`. Pourtant checkout, pod install, keychain, invalidation DerivedData s'additionnent. C'est ce cumul qui produit l'impression 2-3x.
Pourquoi xcodebuild devient 2-3x plus lent en CI
Ces cinq facteurs reviennent dans la plupart des pipelines Flutter iOS, sur GitHub Actions comme en migration auto-hébergée.
- 1) Les runners sans état réinitialisent chaque couche Sur GitHub-hosted, VM neuve à chaque job : SPM, Pods, module cache et index ne restent pas durablement chauds.
- 2) Chemin DerivedData instable = perte d'incrémental Si le chemin change, xcodebuild ne réutilise plus correctement les artefacts et recompilera davantage.
- 3) Résolution Flutter plugins + Pods à froid Les variations de lockfile et de plugins rendent `pod install` long et imprévisible sans discipline de déploiement.
- 4) Signature et keychain ajoutent une latence sérielle Import certificats, création/déverrouillage keychain prennent du temps fixe à chaque exécution CI.
- 5) Pression disque/inode ralentit l'écriture Regarder seulement CPU masque le vrai problème : peu d'espace libre et saturation inode freinent index et sorties build.
Table des temps par étape (exemple Flutter iOS)
Mesurez d'abord ce tableau sur au moins dix runs avant de changer d'architecture.
| Étape | Mac local | GitHub Actions | Cause fréquente |
|---|---|---|---|
| flutter pub get | 0m25s | 1m10s | cache pub insuffisamment chaud |
| pod install | 1m30s | 4m45s | Specs/plugins résolus à froid |
| xcodebuild compile/archive | 6m40s | 12m20s | DerivedData non réutilisé |
| codesign/export | 0m55s | 2m00s | bootstrap keychain répété |
| total | 9m30s | 20m15s | environ 2.1x plus lent |
Avant d'accuser xcodebuild
Avant d'optimiser xcodebuild, regardez pod install. CocoaPods ralentit en CI pour trois raisons récurrentes :
Podfile.locknon commité — résolution imprévisible.- Pas de cache
ios/Pods— artefacts supprimés après le job. pod repo updateinutile — le lockfile suffit en CI.
Utilisez pod install --deployment et gardez Pods sur le même SSD. Un Mac mini self-hosted évite l'upload/download de caches GitHub.
DerivedData, Pods et cache : architecture pragmatique
Sur Flutter iOS, le plus rentable est souvent de fixer un chemin absolu DerivedData et de rendre CocoaPods prévisible. Avec runner auto-hébergé, la CI devient une machine durablement optimisable.
Même en GitHub-hosted, imposez des chemins et lockfiles déterministes. Si possible, louer un Mac Apple Silicon et passer en auto-hébergé rapproche le comportement du local.
- Un derivedDataPath stable par cible applicative.
- `pod install --deployment` pour éviter la dérive lockfile.
- Suivre espace disque libre et inodes comme métriques CI majeures.
Pattern de correction : chemins stables + restore déterministe
Le snippet ci-dessous reste volontairement simple : robustesse d'exploitation avant optimisation fragile.
- Ajouter
concurrency— annuler les builds obsolètes sur la branche. - Tests sur Linux — ne pas consommer le Mac pour
flutter test. - Persister Pods + DerivedData — chemins fixes en self-hosted, clés cache fines en hosted.
- Builder seulement le flavor livré — pas six flavors pour un IPA.
- Épingler Xcode/Flutter — pas d'
upgradedans la CI.
# .github/workflows/ios-ci.yml
jobs:
ios:
runs-on: [self-hosted, macOS, ARM64, flutter-ios]
steps:
- uses: actions/checkout@v4
- name: Restore caches
run: |
mkdir -p "$HOME/Library/Caches/CocoaPods"
mkdir -p "$HOME/.pub-cache"
- name: Build with stable DerivedData path
run: |
flutter pub get
cd ios
xcodebuild -workspace Runner.xcworkspace -scheme Runner -configuration Release -destination 'generic/platform=iOS' -derivedDataPath "$HOME/ci-derived/runner" CODE_SIGNING_ALLOWED=NO
- name: Keep pod install deterministic
run: |
cd ios
pod install --deployment
Cette base suffit souvent pour récupérer 30-50% du temps, puis affiner via un pool de runners auto-hébergés.
Checklist pré-merge contre les régressions de vitesse
À lancer après chaque upgrade Flutter ou Xcode.
- ☐ CI en Release/IPA, comparaison locale en Debug
- ☐ Job avec
flutter cleanou suppression DerivedData - ☐ Logs
pod installavec Installing massif à chaque run - ☐ Runner GitHub-hosted sans cache SSD local
- ☐ Machine 16 Go avec plusieurs jobs ou simulateurs
- ☐ Changement README déclenche build iOS complet
- ☐ Version Xcode CI différente du poste local
Cochez les trois premiers : priorité cache. Les deux derniers : déclencheurs et taille machine.
FAQ
GitHub Actions est-il toujours plus lent que le local ?
Pas toujours, mais c'est fréquent en Flutter iOS quand les couches de cache restent froides. L'auto-hébergement réduit souvent l'écart.
Faut-il migrer immédiatement vers un runner auto-hébergé ?
Mesurez d'abord. Si le coût de cold start domine, migrez un workflow pilote et comparez la médiane sur dix runs.
Faut-il du matériel coûteux ?
Souvent non. louer un Mac Apple Silicon avec cache persistant apporte déjà un gain net.
Comment convaincre l'équipe ?
Montrez les timings par étape, convertissez les minutes en coût d'attente et ajoutez le bénéfice de prédictibilité release.
Liens liés du cluster
Pour corriger durablement la lenteur xcodebuild en CI, suivez cet ordre.
- Hub : architecture Flutter iOS CI
- Dossier cache : DerivedData, CocoaPods, SPM
- Runner auto-hébergé GitHub Actions sur cloud Mac
- Signature iOS CI sans chaos keychain
- Surveillance disque/inode pour runners longue durée
Besoin d'une vitesse iOS CI stable sur Apple Silicon réel ?
kvmboot cloud Mac propose des hôtes dédiés M-series pour Flutter iOS. Commencez par louer un Mac à la journée, puis passez au runner auto-hébergé mensuel.
Si vous voulez remplacer la variabilité CI par des releases prévisibles, voir les offres cloud Mac