Vuncloud Blog
← Retour aux Notes de terrain

Pourquoi votre CI iOS GitHub Actions traîne : cache CocoaPods, SPM et DerivedData (2026)

Notes de terrain · Cacher CocoaPods / SPM / DerivedData sur GitHub Actions · Exemples workflow ·~12 min de lecture

Optimisation cache CI iOS GitHub Actions : CocoaPods SPM DerivedData builds Xcode lents
L'essentiel d'abord

Quand la CI iOS sur GitHub Actions semble lente, le coupable n'est rarement la CPU — c'est le cache absent ou des clés mal choisies, à trois endroits :

  • CocoaPods : pas de cache Pods/ → chaque run refait pod install
  • Swift Package Manager (SPM) : graphe de dépendances re-résolu ; .build effacé à chaque job
  • Xcode DerivedData : cold builds → compilation Swift complète et rebuild des modules

Bien câbler le cache CocoaPods sur GitHub Actions, le cache SPM et le cache DerivedData, et le warm build chute souvent de 30 % à 60 % (comparaison Shadow dans la cascade waterfall).

30–60%
réduction typique du warm build
3
CocoaPods · SPM · DerivedData
1–5 min
gain courant par couche (cache seul)

1. Pourquoi la CI iOS GitHub Actions traîne

La première question d'équipe : « macos-latest est sous-dimensionné ? » « On passe au M4 ou à plus gros ? »

Dans les vrais cas de ralentissement Xcode CI, le goulot n'est rarement la CPU. Ce sont trois coûts cachés :

  1. Re-résolution des dépendances (CocoaPods / SPM)
  2. Cold starts DerivedData (recompilation complète)
  3. Misses actions/cache — chaque run ressemble à un premier build

GitHub Actions amplifie le phénomène : runners éphémères (disque propre à chaque job), le cache ne « colle » pas tout seul, et les setups multi-branches / multi-jobs polluent les clés. Si vous cherchez pourquoi le même commit compile vite un run et lentement le suivant, séparez d'abord cold vs warm, puis ajustez le cache avec ce guide terrain.

2. Où part vraiment le temps en CI iOS

2.1 CocoaPods (cache Pods)

Coût cold typique : pod install environ 3 à 8 minutes.

Cause : chaque run CI relance pod install — resolve, download, integrate depuis zéro.

Correctif : cacher Pods/ avec actions/cache ; clé = hash Podfile.lock + github.ref + arm64. En CI, pod install --deployment.

2.2 Swift Package Manager (SPM)

Coût typique : résolution du graphe 1 à 5 minutes.

Cause : re-résolution à chaque run ; .build effacé ; Package.resolved absent de la clé cache.

Correctif : cacher ~/Library/Caches/org.swift.swiftpm et .build ; clé incluant le hash Package.resolved (voir §3.2).

2.3 Xcode DerivedData

Surcoût cold typique : compilation complète ou quasi 5 à 15 minutes.

Cause : DerivedData non réutilisé → compile Swift complète, retraitement assets, rebuild modules.

Correctif : xcodebuild -derivedDataPath DerivedData et cacher ce chemin (voir §3.3).

Équipe passant en revue un workflow GitHub Actions pour cache CocoaPods, SPM, DerivedData et optimisation CI iOS

3. Une configuration cache CI iOS GitHub Actions qui tient la route

Pour runs-on: macos-latest. Placez les trois blocs dans le même job, avant pod install / xcodebuild (actions/cache@v4 sauvegarde automatiquement).

3.1 Cache CocoaPods (obligatoire)

Cache CocoaPods · GitHub Actions
- name: Restore Pods cache
  uses: actions/cache@v4
  with:
    path: Pods
    key: pods-arm64-${{ github.ref }}-${{ hashFiles('**/Podfile.lock') }}
    restore-keys: |
      pods-arm64-${{ github.ref }}-

- name: Pod install
  run: pod install --deployment

3.2 Cache SPM (obligatoire)

Cache SPM · CI iOS
- name: Restore SPM cache
  uses: actions/cache@v4
  with:
    path: |
      ~/Library/Caches/org.swift.swiftpm
      .build
    key: spm-arm64-${{ github.ref }}-${{ hashFiles('**/Package.resolved') }}
    restore-keys: |
      spm-arm64-${{ github.ref }}-

3.3 Cache DerivedData (fort impact)

Cache DerivedData · xcodebuild
- name: Restore DerivedData cache
  uses: actions/cache@v4
  with:
    path: DerivedData
    key: dd-arm64-${{ github.ref }}-${{ hashFiles('**/Podfile.lock') }}
    restore-keys: |
      dd-arm64-${{ github.ref }}-

- name: Build iOS
  run: xcodebuild -scheme MyApp -derivedDataPath DerivedData ...

Attendez Cache hit occurred dans les logs avant de comparer les durées d'étapes. En cas de miss, corrigez d'abord clé et chemin — ne blâmez pas encore la version Xcode.

4. Design des clés cache (ne pas zapper)

Beaucoup d'efforts d'optimisation CI iOS échouent sur les clés, pas sur les runners.

✔ À inclure ❌ Erreurs courantes
Architecture (arm64) Pas de split arm64/x86 — changez de runner, tout miss
Branche (github.ref) Lockfile seul — DerivedData se mélange entre branches
Hash lockfile restore-keys trop large (ex. préfixe dd-) → mauvais hit
Fallback restore-keys

Quand le lockfile change, un préfixe comme dd-arm64-${{ github.ref }}- peut réutiliser partiellement le cache. Multi-schemes ? Ajoutez ${{ matrix.scheme }} à la clé. Jobs concurrents sur un même runner ne doivent pas partager un seul root DerivedData — isolez avec des sous-dossiers ${{ github.run_id }}.

5. Self-hosted / Cloud Mac (avancé)

Sur Mac mini ou Cloud Mac en runner self-hosted, vous n'êtes pas limité à actions/cache — le disque persiste et les warm builds sont plus stables :

  • Chemin DerivedData fixe
  • Répertoire Pods fixe
  • Cache warm sur disque (économise 30–90 s d'upload/download par job)
Self-hosted · chemins fixes
export DERIVED_DATA=/Volumes/Data/DerivedData/App-${{ github.run_id }}
export PODS_ROOT=/Volumes/Data/Pods/${{ github.ref_name }}

Exemple de job complet et disque données 1 To : workflow ci-dessous et FAQ branchement CI/CD.

Self-hosted · DerivedData + Pods fixes
env:
  DERIVED_DATA: /Volumes/Data/DerivedData/App-${{ github.run_id }}
  PODS_ROOT: /Volumes/Data/Pods/${{ github.ref_name }}

jobs:
  build:
    runs-on: [self-hosted, macos-m4-ios]
    steps:
      - uses: actions/checkout@v4
      - name: Prepare dirs
        run: mkdir -p "$DERIVED_DATA" "$PODS_ROOT"
      - name: Pod install
        run: pod install --deployment
      - name: xcodebuild
        run: xcodebuild -scheme MyApp -derivedDataPath "$DERIVED_DATA" build

6. Cache miss ≠ runner lent (erreur fréquente)

Les équipes attribuent souvent une CI iOS GitHub Actions lente au runner ou à la version Xcode. Plus souvent :

Ce que vous voyez Cause plus probable
Build soudainement plus lent Cache miss
P95 instable Cold builds mélangés aux stats warm
Ralentissements aléatoires Contention DerivedData entre jobs parallèles
Dépendances reconstruites from scratch Mauvaise clé cache

À croiser avec le guide variance de build : séparer cold/warm → tuner le cache → puis évaluer le matériel (2026 : pourquoi la CI/CD iOS tourne sur Mac mini M4).

7. Gains mesurés

Correctifs cache seuls, économies typiques :

Couche Temps en plus sur cold miss Après cache câblé
CocoaPods 3–8 min warm souvent <30 s–3 min
SPM 1–5 min resolve bien plus court sur hit
DerivedData 5–15 min warm surtout compile incrémentale

Sur notre run Shadow 14 jours, l'optimisation cache seule a réduit le wall clock warm d'environ −1:40. En éliminant la file et en passant self-hosted avec disque fixe, warm P95 14:12 → 6:05 (−57 %) — voir la vue d'ensemble optimisation.

8. FAQ

Pourquoi la CI iOS GitHub Actions est-elle si lente ?

Pas la CPU en général — CocoaPods / SPM / DerivedData sans cache ou mal clés. Les runners éphémères amplifient chaque miss.

Comment cacher CocoaPods sur GitHub Actions ?

Cacher Pods/ ; clé : pods-arm64-${{ github.ref }}-${{ hashFiles('**/Podfile.lock') }}. Voir §3.1.

Comment cacher SPM en CI iOS ?

Cacher le répertoire swiftpm global et .build ; lier la clé à Package.resolved. Voir §3.2.

Quel chemin pour le cache DerivedData ?

Le path de actions/cache doit correspondre à xcodebuild -derivedDataPath ; le défaut système n'est pas obligatoire.

Cache trop volumineux ?

GitHub plafonne chaque entrée à environ 10 Go. Scindez les clés DerivedData par scheme, ou self-hosted avec disque fixe sans upload.

macos-latest vs self-hosted ?

Hosted : seulement actions/cache, peut vider entre jobs. Self-hosted : /Volumes/Data fixe, warm builds plus stables. Comparaison dans la vue d'ensemble optimisation.

9. Bilan et guides associés

Le meilleur ROI en optimisation CI iOS est souvent de câbler les caches CocoaPods, SPM et DerivedData — avant de changer de puce. Modifiez le workflow aujourd'hui et lancez une PR de test.

Même série :

Des chemins DerivedData et Pods fixes ?

Vuncloud Cloud Mac M4 Pro avec disque données 1 To — pensé pour CI iOS self-hosted : moins de shuffle via actions/cache, warm builds plus stables.

Voir les offres Cloud Mac · FAQ branchement CI/CD

Notes de terrain · CI iOS

CI iOS lente ? Commencez par ces trois caches

CocoaPods · SPM · DerivedData · exemples workflow

Cascade −1:40
Offre limitée Voir les offres