NOTE D’INGÉNIERIE

Builds Xcode hébergés ou Mac cloud autogéré

Builds Xcode hébergés ou Mac cloud autogéré

Builds Xcode hébergés ou Mac cloud autogéré

L’équipe dispose déjà d’un pipeline iOS fonctionnel, mais chaque ajout de dépendance, changement de version de Xcode ou ajustement de la signature relance le même débat : faut-il continuer à utiliser des builds hébergés ou exécuter les tâches sur un Mac cloud autogéré ? Ne commencez pas par comparer les quelques secondes gagnées sur un build. À long terme, les véritables facteurs de coût sont la reproductibilité de l’environnement, la maîtrise du cache, la conservation du contexte en cas d’échec et la charge d’exploitation assumée par les ingénieurs.

Commencer par classer les charges de travail en trois catégories

Avant de choisir une plateforme, analysez les tâches des deux dernières semaines plutôt que de vous fier à des impressions. Il est recommandé de les répartir en trois catégories : contrôles de fusion, archivage pour publication et diagnostics ponctuels. Les contrôles de fusion sont généralement courts, avec des entrées bien définies, et peuvent être relancés après un échec. L’archivage pour publication implique les éléments de signature, la conservation des artefacts et un verrouillage strict des versions. Les diagnostics ponctuels exigent quant à eux que les ingénieurs puissent accéder au même environnement afin de reproduire le problème.

Consignez au minimum les données suivantes :

Élément Informations à consigner Objectif
Chaîne d’outils Versions de macOS, Xcode, Ruby et des gestionnaires de paquets Évaluer la difficulté à figer l’environnement
Entrées Révision, fichiers de verrouillage et paramètres de build Déterminer si la tâche est reproductible
Étapes Durées de mise en file d’attente, d’exécution, d’envoi et de nettoyage Identifier le véritable goulot d’étranglement
Contexte Journaux, result bundle et archives produites Évaluer les capacités d’analyse des incidents
Cache Chemins, tailles, conditions de correspondance et modes d’invalidation Évaluer les bénéfices à long terme

Un succès isolé ne signifie pas que le processus est stable. Exécutez au moins trois fois la même révision, puis vérifiez de nouveau le comportement du cache avec une révision qui ne modifie que le code métier, sans toucher aux dépendances.

Établir une empreinte d’environnement commune

Les deux approches doivent utiliser le même script de contrôle de l’environnement. Ne vous contentez pas d’afficher xcodebuild -version : consignez également la version du système, le répertoire de développement actif, le SDK, Ruby et l’état des gestionnaires de paquets. Le fichier d’empreinte doit être conservé comme un artefact ordinaire de chaque tâche. En cas d’échec, comparez-le avant d’examiner le code métier.

#!/bin/zsh
set -euo pipefail

mkdir -p artifacts
{
  sw_vers
  uname -m
  xcodebuild -version
  xcode-select -p
  xcrun --sdk iphoneos --show-sdk-version
  ruby --version
  git --version
} > artifacts/environment.txt

export DEVELOPER_DIR="/Applications/Xcode.app/Contents/Developer"
xcodebuild \
  -workspace App.xcworkspace \
  -scheme App \
  -configuration Release \
  -derivedDataPath "$PWD/.build/DerivedData" \
  -resultBundlePath "$PWD/artifacts/App.xcresult" \
  build

DEVELOPER_DIR ne doit pas pointer vers un chemin qui n’a pas été vérifié. Un environnement autogéré peut conserver plusieurs versions de Xcode, mais le pipeline doit en sélectionner une explicitement. Dans un environnement hébergé, la version réellement disponible doit être vérifiée au début de la tâche, avec un arrêt immédiat en cas d’incompatibilité. Cela évite de ne découvrir une différence de SDK qu’au stade de l’archivage.

Valider séparément le cache, la signature et la concurrence

Ne pas transférer des répertoires entiers dans le cache

La clé de cache doit au minimum inclure la version majeure de Xcode, l’architecture et l’empreinte des fichiers de verrouillage des dépendances. SwiftPM, CocoaPods et les répertoires intermédiaires de build doivent être gérés séparément, car leurs conditions d’invalidation diffèrent. Évitez de restaurer l’intégralité du répertoire utilisateur : vous réintroduiriez d’anciennes autorisations, des fichiers temporaires et des configurations invisibles dans chaque nouvelle tâche.

Un Mac cloud autogéré convient aux pipelines qui doivent conserver durablement de volumineux caches de dépendances. Chaque dépôt doit toutefois disposer de son propre répertoire de travail, et il faut vérifier régulièrement qu’un build complet reste possible après suppression du cache. Dans les builds hébergés, le cycle de vie du cache est généralement contrôlé par la plateforme. Il doit donc être considéré comme une optimisation, et non comme une condition de réussite.

Limiter la visibilité des éléments de signature à la durée de la tâche

Les éléments de signature doivent être injectés depuis un stockage contrôlé au début de la tâche, puis leurs copies temporaires supprimées immédiatement à la fin. Les journaux ne doivent jamais afficher de mot de passe, de contenu de clé ni de chemin de fichier complet. Quelle que soit l’approche retenue, vérifiez que le nettoyage s’exécute aussi dans les branches d’échec, et pas uniquement après un succès.

Les tests de concurrence doivent commencer avec deux tâches. Vérifiez si elles partagent DerivedData, des simulateurs, un Keychain ou des ports fixes. Dès lors qu’un état partagé et modifiable existe, l’augmentation de la concurrence risque d’amplifier les défaillances intermittentes.

Tester la récupération à l’aide d’exercices de panne

N’attendez pas l’échec d’une véritable publication pour valider la procédure de récupération. Vous pouvez organiser quatre exercices sans effet destructeur : spécifier volontairement un scheme inexistant, supprimer un cache de dépendances, faire échouer un test et interrompre la tâche avant l’archivage. Contrôlez à chaque fois le code de sortie, la fin des journaux, le result bundle, les éléments de signature temporaires et l’état du répertoire de travail.

Pour les builds hébergés, vérifiez en priorité si les journaux suffisent à expliquer l’échec, si l’environnement peut encore être reproduit et si les entrées sont strictement identiques lors d’une nouvelle exécution. Sur un Mac cloud autogéré, assurez-vous également que les processus résiduels, les répertoires montés et les ports ne contaminent pas la tâche suivante. Il est recommandé d’attribuer un répertoire unique à chaque tâche et d’utiliser un hook de sortie pour terminer les processus enfants.

workdir="$(mktemp -d "$PWD/.job.XXXXXX")"
cleanup() {
  jobs -p | xargs -r kill 2>/dev/null || true
  rm -rf "$workdir"
}
trap cleanup EXIT INT TERM

Le script de nettoyage doit d’abord être validé dans un répertoire de test afin d’éviter qu’un caractère générique trop large n’affecte d’autres tâches. Les journaux et artefacts de build à conserver doivent être copiés dans un répertoire artifacts distinct avant de lancer le nettoyage.

Décider selon le niveau de contrôle, pas selon les slogans

Si le projet utilise des dépendances classiques, que les tâches sont courtes, qu’un échec peut être traité par une simple relance et que l’équipe ne souhaite pas gérer l’état des machines, les builds hébergés sont généralement plus adaptés. Si vous devez figer plusieurs versions de Xcode, réutiliser durablement les caches, exécuter des outils spécifiques, accéder directement à l’environnement pour diagnostiquer un problème ou laisser tourner de longues tâches, un Mac cloud autogéré permet plus facilement d’établir des limites claires.

Les deux approches peuvent aussi être combinées : les demandes de fusion exécutent des tests légers, tandis que les branches stables utilisent l’environnement autogéré pour l’archivage et les diagnostics approfondis. L’essentiel est de partager la même empreinte d’environnement, les mêmes fichiers de verrouillage, le même point d’entrée de build et les mêmes conventions de nommage des artefacts afin d’éviter la création de deux pipelines incompatibles.

La validation finale ne doit pas reposer sur l’exécution la plus rapide, mais sur le taux de réussite de plusieurs exécutions, le nombre de différences entre environnements, la capacité de récupération après suppression du cache, l’exhaustivité des éléments disponibles en cas d’échec et les interventions manuelles nécessaires. Consignez ces résultats dans un journal de décision au sein du dépôt et prévoyez une nouvelle évaluation après tout changement de version majeure de Xcode, de système de dépendances ou de volume de tâches. Le choix initial ne deviendra ainsi pas une hypothèse permanente.

Questions fréquentes

Les builds hébergés sont-ils toujours plus simples à exploiter ?

Non. Ils conviennent aux projets standardisés, mais un environnement autogéré est souvent plus direct pour figer Xcode, conserver les caches ou analyser précisément un échec.

Peut-on combiner les deux modèles ?

Oui. Les contrôles de fusion peuvent rester hébergés, tandis que les archives exigeant des caches stables, une signature complexe ou des journaux complets utilisent le Mac cloud.

Quel test faut-il effectuer avant de choisir ?

Exécutez plusieurs fois le même commit avec les mêmes fichiers de verrouillage et commandes, puis mesurez la stabilité, les caches, les journaux et le temps de reprise.

VMDebug Mac physiques dans le cloud

Besoin d’un Mac mini physique dédié à une seule commande ?

Comparez les configurations M4 et M4 Pro, les quatre durées de location et les cinq nœuds disponibles, puis choisissez l’appareil adapté à votre workflow.

Choisir une configuration et commander