2026 SwiftPM et CocoaPods sur Mac distant partagé (CI) Package.resolved · isolation Bundler · gouvernance disque DerivedData

Sur un Mac distant partagé ou dédié, faire coexister SwiftPM et CocoaPods oppose Package.resolved, Gemfile.lock et DerivedData aux quotas disque pendant que des jobs concurrents écrasent les mêmes chemins. Cet article propose aux équipes plateforme une checklist de validation : sept coûts cachés, un tableau comparatif SPM seul vs Pods seul vs pile mixte, un runbook disque et cache en six étapes, et la lecture avec nos guides builds reproductibles, runner auto-hébergé et snapshots vs nœuds longue durée.

01

Avant de mélanger les piles : sept coûts cachés qui font exploser les lockfiles et le disque sur un Mac distant partagé (CI)

Sous Linux vous répartissez caches de dépendances et sorties de build sur plusieurs volumes. Sur un hôte macOS partagé, les checkouts SwiftPM, l’arborescence Pods et DerivedData se retrouvent souvent par défaut sous un même répertoire personnel ; avec des dépôts parallèles, la pression disque ou inode arrive avant le CPU. Utilisez les sept points ci-dessous comme revue préalable.

  1. 01

    Package.resolved vs dérive de politique de branches : sans compartiments par branche, des branches parallèles peuvent résoudre correctement mais lier de mauvais artefacts.

  2. 02

    Dérive de l’écosystème Ruby pour CocoaPods : mélanger Ruby système, rbenv et Bundler donne des versions pod incohérentes—vert en local, flaky en CI.

  3. 03

    Racines DerivedData partagées : plusieurs jobs écrivant un même -derivedDataPath écrasent caches modules et index ; les échecs ressemblent à des dépendances corrompues.

  4. 04

    Tiers en double entre Pods et SPM : la même bibliothèque deux fois double téléchargement et temps de résolution, souvent absent de la revue d’architecture.

  5. 05

    Scripts de nettoyage qui suppriment des caches vivants : des tâches cron basées seulement sur l’âge peuvent retirer des artefacts pour du travail en file et provoquer des cascades d’échecs.

  6. 06

    Politique CDN / miroir incohérente : quand pod repo update et la résolution SPM n’empruntent pas les mêmes sorties réseau, le jitter devient « la CI est instable ».

  7. 07

    Aucun contrat de seuil disque : sans seuil défini pour arrêter le scheduling ou passer en lecture seule, l’hôte tombe disque plein avant qu’on le remarque—coûteux à réparer.

La cause commune est d’importer le modèle mental « un dépôt, une pipeline » depuis un VPS Linux vers un Mac multi-locataire : il faut des caches et lockfiles namespacés, pas seulement un disque plus grand. Consignez-les dans votre registre plateforme, puis servez-vous du tableau suivant pour décider de converger les piles ou d’accepter des piles mixtes avec des frontières répertoire strictes.

SwiftPM encode la résolution reproductible dans Package.resolved avec le résolveur du compilateur ; CocoaPods reste lié à Ruby et souvent Bundler en entreprise. Le pire schéma laisse les ingénieurs modifier les gems globales depuis un shell interactif sur la CI—injectant de l’entropie sur chaque hôte partagé. Préférez un Gemfile.lock versionné, uniquement bundle exec pod install, et vendor/bundle sur une partition que vous pouvez effacer sans risque.

À lire avec les builds reproductibles : les scripts d’empreinte doivent capturer les sommes de contrôle de swift package resolve et pod --version, pas seulement Xcode.

À lire avec les runners : si vous montez des caches sur volumes partagés, scopez par sous-répertoire de dépôt—pas un DerivedData géant pour tout le monde.

Les contrôles réseau et CDN reviennent à la section 4 à côté de Bundler. Ensuite le tableau comparatif transforme les débats en règles de partitionnement.

02

SwiftPM seul, CocoaPods seul ou mixte : compromis répertoire et risque sur Mac distants partagés

Il n’existe pas de solution universelle : SPM seul garde des chemins homogènes mais l’ObjC hérité exige souvent encore Pods ; Pods seul est familier mais Ruby et le CDN coûtent plus en exploitation. Inscrivez trois SLA dans la revue : répétabilité de résolution, pics disque et échecs explicables.

DimensionSwiftPM d’abordCocoaPods d’abordMixte (legacy courant)
Lockfiles et répétabilitéPackage.resolved trace le couplage résolveur/compilateurPodfile.lock + Ruby/Bundler doivent être figésDeux lockfiles et deux arbres de cache—surveiller dépendances dupliquées et collisions de chemins
Profil disqueCheckouts + cache SPM—relativement prévisiblePods est volumineux ; la toolchain Ruby ajoute du surcoûtLes pics s’additionnent—compartimentez DerivedData explicitement
ConcurrenceIsolation répertoire facile ; bon pour le parallélismepod install peut retenir des verrous—mettez-le en fileSéparez les répertoires de travail ; jamais deux écrivains sur un même chemin
Leviers d’exploitationS’aligne sur la toolchain Xcode—colle aux scripts d’empreinteMaintenir sources gem, CDN, politique de cache BundlerRunbook le plus long, mais la plupart des apps réelles aboutissent là
Images de référencePréchauffer les couches de cache SPMSouvent Ruby + Pods connus dans les baselinesLes images grossissent—séparer toolchain / deps / couches mutables

Louer un Mac « comme un VPS » au niveau dépendances, c’est acheter des contrats répertoire et seuils prévisibles, pas espérer que le disque du portable tienne. Traitez les caches SPM et Pods comme des locataires, pas comme du bruit de fond.

Si vous exploitez un pool de build entreprise, séparez les jobs « résolution de dépendances » des jobs « signature et release » : les premiers tolèrent un nettoyage agressif ; les seconds ne doivent pas partager un répertoire personnel avec des états Bundler expérimentaux. Avec snapshots vs nœuds longue durée : les piles mixtes sur hôtes vivants demandent un nettoyage hebdomadaire plus des seuils ; les baselines snapshot profitent d’un préchauffage en couches de Bundler et SPM.

Quand la décision est « on ne peut pas encore retirer Pods », encodez des règles : quels tiers restent strictement SPM vs Pod uniquement (ex. binaires propriétaires), et interdisez le même module par les deux canaux ou vous paierez au lien. Fournissez des extraits minimaux de Gemfile et .bundle/config depuis un dépôt modèle pour que les équipes copient au lieu d’inventer par service.

03

Six étapes pour transformer « SPM + Pods sur un Mac distant partagé » en runbook transmissible

L’ordre compte : partitionner d’abord, résoudre ensuite, hits de cache en dernier. Alignez les empreintes sur l’article builds reproductibles pour que les couches de dépendances n’introduisent pas une seconde environnement non documenté.

  1. 01

    Fixer une racine de travail et un compartiment de branche par dépôt : ex. /ci/work/<repo>/<branch-hash> ; garder checkouts SPM, Pods et DerivedData sous ce compartiment—ne jamais retomber sur les chemins par défaut ~/Library.

  2. 02

    Figez Bundler et CocoaPods : dans l’image CI ou le script de boot, n’utiliser que bundle exec et pointer BUNDLE_PATH vers vendor/bundle dans le compartiment.

  3. 03

    Observer la résolution SwiftPM séparément du build : chronométrez la résolution ; en cas d’échec conservez les journaux près de .build pour ne pas confondre erreurs de résolveur et de compilation.

  4. 04

    Isoler DerivedData par job : toujours passer un -derivedDataPath explicite à xcodebuild avec la racine de travail ci-dessus.

  5. 05

    Définir une politique de nettoyage : déclencher sur seuil, exécuter dans les fenêtres creuses, évincer en LRU ; jamais de rm -rf ~/Library aveugle.

  6. 06

    Câbler les labels runner : selon le guide runner, limiter les jobs lourds pod install sur leur propre label ; ne pas affamer les jobs très compilants.

bash · exemple d’environnement work-bucket (à ajuster par projet)
export CI_WORK_ROOT="/ci/work/${REPO_SLUG}/${BRANCH_KEY}"
export DERIVED_DATA="${CI_WORK_ROOT}/DerivedData"
export PODS_ROOT="${CI_WORK_ROOT}/Pods"
export BUNDLE_PATH="${CI_WORK_ROOT}/vendor/bundle"
mkdir -p "$DERIVED_DATA"
bundle config set path "$BUNDLE_PATH"
bundle exec pod install --deployment
swift package resolve
info

Astuce : si le même hôte exécute aussi des releases Fastlane, gardez des compartiments release séparés des compartiments de résolution CI pour éviter que Bundler et les outils App Store Connect ne se contaminent.

Sur GitHub Actions et plateformes similaires, séparez « installer les dépendances » de « build/test » et clefiez les caches sur le contenu des lockfiles, pas seulement sur les noms de branches. Si un workspace mélange SPM et Pods, figez les arguments xcodebuild -workspace pour que les habitudes GUI ne divergent pas indéfiniment de la CI.

Avec XCTest / Simulateur : si les tests réutilisent le DerivedData de compilation, déclarez explicitement la portée lecture vs écriture ; sinon le nettoyage des tests peut détruire les caches de compilation. Documentez « qui peut supprimer quoi » comme pour des volumes conteneurs sous Linux.

04

Bundler, CDN et repli lecture seule : garder le jitter réseau hors du « le code est cassé »

L’incident CocoaPods le plus fréquent en production n’est pas une erreur de syntaxe—c’est une panne réseau au moment de la résolution lue à tort comme bug applicatif. Donnez aux hôtes partagés une politique de miroir gem unique et une politique de transport Git (HTTPS vs SSH), autorisez les noms d’hôte de métadonnées au pare-feu, et intégrez timeouts et nouvelles tentatives pour pod install dans les workflows plutôt que les valeurs par défaut.

Pour SwiftPM, vérifiez si Package.resolved correspond encore au résolveur après une montée majeure de Xcode : exécutez swift package resolve plus un build minimal dans un job canari avant d’ouvrir les vannes. Alignez avec les builds reproductibles : tout changement de lockfile doit avertir que les caches de résolution partagés peuvent nécessiter une invalidation, pas une pollution silencieuse.

warning

Attention : n’acceptez pas de nouveaux jobs au bord du disque plein—passez en repli lecture seule (arrêt du scheduling) et nettoyez d’abord ; sinon Xcode et git peuvent laisser un état à moitié écrit plus coûteux qu’une courte pause de file.

Pour des flottes multi-régions, tracez taux de hit CDN et latence de résolution : quand le P95 grimpe, suspectez les miroirs avant de demander aux équipes « trois nouveaux essais ». Couplez avec la checklist SSH : déployez les versions Bundler et pod via gestion de configuration, pas par upgrades SSH ad hoc.

05

Chiffres de référence pour une revue de conception

Ajustez les seuils à votre parallélisme et à la taille des dépôts ; les valeurs suivantes servent d’ancrage.

  • Seuil volume système (partagé) : conserver au moins 20 % d’espace libre ; en dessous, suspendre le scheduling avant toute suppression et journaliser ce qui est retiré pour audit.
  • Pics double pile : sur de grosses apps iOS, DerivedData + Pods + checkouts SPM atteignent couramment des dizaines de Go—dimensionnez pour le dépôt le plus lourd × jobs concurrents × marge de sécurité, pas pour un build isolé.
  • Sondes de répétabilité de résolution : les scripts d’empreinte doivent enregistrer le statut de sortie de swift package resolve, bundle exec pod --version et une somme de contrôle de Podfile.lock comme garde-fous de fusion.

Les ordinateurs portables dorment et font dériver la toolchain, ce qui rend les problèmes de dépendances opaques ; le Linux pur n’héberge pas la pile iOS officielle d’Apple. Déplacer résolution et build vers un Mac distant dédié, toujours joignable et partitionnable transforme SwiftPM et CocoaPods en contrat. Par rapport au matériel ponctuel ou à un hébergement partagé fragile, la location cloud de Mac Mini NodeMini associe SSH fixe, paliers disque clairs et profils de nœuds reproductibles—mieux pour une gouvernance des dépendances digne d’une plateforme. Comparez les paliers sur la page des tarifs de location et l’onboarding via le centre d’aide.

Liez ce runbook à vos « niveaux de changement de dépendances » internes : patchs de lockfile vs mineur vs majeur doivent emporter des approbations et règles d’invalidation de cache différentes.

FAQ

FAQ

Ce n’est pas recommandé. Répartissez -derivedDataPath par compartiment dépôt/branche et isolez Pods et les chemins vendor Bundler ; sinon des jobs concurrents écrasent les caches. Pour l’orientation plateforme, voir le centre d’aide.

Les versions Ruby et Bundler, Gemfile.lock et la politique de miroir CDN pour pod install ; puis définir des seuils de nettoyage par hôte partagé. Comparez les paliers disque sur la page des tarifs de location.

Les builds reproductibles couvrent les empreintes Xcode et le trousseau ; l’article runner les labels et les montages de cache ; cet article les contrats répertoire et disque en mélangeant SPM et Pods. Lisez les trois pour couvrir machine et dépendances de bout en bout.