Principe du cache Xcode et tableau de correspondance des conditions de hit
Sur un runner distant, le cache de compilation Xcode correspond surtout aux artefacts sous Derived Data : fichiers objets, modules Swift, index, descripteurs de build. Lorsque les entrées (sources, fichiers générés, drapeaux comme OTHER_SWIFT_FLAGS) et l'empreinte de la chaîne d'outils restent alignées, Xcode peut éviter des recompilations et réduire le temps de mur. En iOS CI, un workspace jetable par job ou un chemin aléatoire vers Derived Data détruit le taux de hit : chaque pipeline repart de zéro alors que le matériel pourrait amortir un cache partagé.
La CI/CD exige vitesse et files d'attente stables : un faible hit rate augmente la charge disque et les IOPS, ce qui affecte la stabilité du nœud pour les autres jobs. D'où l'intérêt de figer -derivedDataPath et de versionner la clé de cache (hash de Package.resolved, Podfile.lock, libellé Xcode).
| Condition | Effet sur le hit | Action opérationnelle |
|---|---|---|
| Version Xcode / Swift | Écart → miss quasi certain | Inclure xcodebuild -version et swift --version dans la clé de cache |
| Chemin Derived Data | Chemin stable → hit durable | Toujours -derivedDataPath "$CI_DERIVED_DATA" (persistant par runner ou pool) |
| Dépendances SwiftPM | Changement Package.resolved → invalidation |
-clonedSourcePackagesDirPath "$CI_SPM_DIR" partagé entre jobs compatibles |
| Configuration | Debug ↔ Release → caches distincts | Sous-dossiers DD séparés par configuration ou scheme |
Exemple de clé : macOS + hash(lockfiles) + Xcode_16.2 + scheme. Pour l'alignement des dépendances avant build, voir pré-tirage CI et cohérence des versions sur Mac distant.
Préchauffage et stratégie de nettoyage des nœuds Mac distants
Réutiliser le même exécuteur permet de faire mûrir Derived Data et d'améliorer l'accélération des builds. Le préchauffage combine résolution des paquets et un build représentatif ; le nettoyage doit rester local au projet pour ne pas casser les hits des autres pipelines.
- Chaîne fixe :
export DEVELOPER_DIR=/Applications/Xcode_16.2.app/Contents/Developer - Résolution SPM :
xcodebuild -scheme "VotreApp" -resolvePackageDependencies -clonedSourcePackagesDirPath "$CI_SPM_DIR" -derivedDataPath "$CI_DERIVED_DATA" - Build simulateur (exemple) :
xcodebuild -scheme "VotreApp" -destination 'platform=iOS Simulator,name=iPhone 16' -derivedDataPath "$CI_DERIVED_DATA" -clonedSourcePackagesDirPath "$CI_SPM_DIR" build - Réduire l'indexation en CI :
export COMPILER_INDEX_STORE_ENABLE=NO(jobs automatisés uniquement)
- Alerte : utilisation du volume > 85 % → notification équipe plateforme.
- Action : > 90 % ou espace libre < 20 Go → supprimer d'abord les sous-dossiers Derived Data du projet concerné.
- Diagnostic :
du -sh "$CI_DERIVED_DATA"/* 2>/dev/null | sort -hr | head - Simulateurs :
xcrun simctl delete unavailableen maintenance hebdomadaire
Arbitrage des paramètres face au clean build
Un clean build permanent maximise la reproductibilité au prix d'une charge CPU et disque élevée ; l'incrémental pur est rapide mais peut masquer un état corrompu. La matrice ci-dessous répartit les politiques entre pull requests, intégration et livraisons.
| Pipeline | Posture | Décision côté xcodebuild |
|---|---|---|
| PR / feature | Incrémental prioritaire | Même -derivedDataPath, pas de clean systématique ; en échec, nettoyage partiel. |
| Intégration nocturne | Clean planifié | xcodebuild clean -scheme … ou rotation d'un sous-dossier DD par calendrier. |
| Release / archive | Plutôt clean | Reproductibilité prioritaire ; limiter le cache aux étapes de résolution de dépendances si besoin. |
| Erreurs signature / embed | Clean ciblé | Après provisioning ou entitlements, supprimer le DD du scheme puis relancer. |
Avec CocoaPods, exécutez pod install sur le même runner que le cache des headers et Derived Data — solutions d'accélération Git et CocoaPods sur Mac CI.
Repli en cas d'échec et FAQ sur les seuils d'espace disque
Ordre de repli pour préserver la stabilité des nœuds : (1) nouvelle tentative avec le même CI_DERIVED_DATA ; (2) suppression du sous-dossier Derived Data du projet ; (3) nouveau répertoire vide pour -derivedDataPath ; (4) rotation du runner ou purge globale en fenêtre de maintenance.
- Espace libre (Mo) :
df -m "$CI_DERIVED_DATA" | awk 'NR==2{print $4}'— avertir si < 15 360 Mo (~15 Go), annuler si < 10 240 Mo. - Utilisation (%) :
df -h "$CI_DERIVED_DATA" | awk 'NR==2{gsub(/%/,"",$5); print $5}'— notifier si > 85, limiter les nouveaux jobs si > 92. - Retry : 2 à 3 tentatives, backoff 30–90 s ; si l'IOPS sature, réduire le parallélisme.
Supprimez le Derived Data du projet et vérifiez qu'un seul DEVELOPER_DIR est exporté dans la session CI.
Deux jobs ne doivent pas écrire dans le même -derivedDataPath sans sous-répertoires isolés ou verrou.
Voir la FAQ stabilité des pulls et le centre d'aide MacPull.
Synthèse et prochaines étapes
En résumé : fixer -derivedDataPath et inclure Xcode/Swift dans la clé de cache améliore le taux de hit du cache Xcode ; le préchauffage Derived Data passe par la résolution SPM et un build représentatif ; le nettoyage suit des seuils disque (85 % / 90 % et garde-fous en Go libres) ; les clean build restent pour les releases, l'incrémental pour le quotidien des PR. Un Mac distant dédié permet de conserver ces caches sans concurrence imprévisible.
Pour passer à l'action sans compte : Découvrir l'accueil MacPull et les offres cloud Mac, Comparer les plans tarifaires, Ouvrir la page d'achat et choisir un forfait, Consulter le centre d'aide, Revenir au blog technique (pages publiques, sans connexion obligatoire).
Nœud de build dédié pour Xcode
Caches Derived Data et SPM sur la durée : réduisez le temps de mur. Tarifs, achat, accueil et aide accessibles sans compte.