Sommaire
Trois douleurs récurrentes dans un pool Mac « partagé » sans gouvernance Xcode
Sans cadre écrit, les incidents ressemblent à des bugs Xcode alors qu’il s’agit de collisions d’état. Les équipes support voient alors des tickets impossibles à rejouer.
- 1Concurrence implicite sur le même
DerivedDataou le même trousseau de signature : échecs intermittents decodesignou profils manquants. - 2Confusion SSH : on sécurise le tunnel mais on mélange encore comptes interactifs et compte de build, ce qui mélange aussi les trousseaux visibles.
- 3Files sans borne : les jobs s’empilent jusqu’à saturer disque et CPU ; les timeouts deviennent des heures silencieuses sans signal métier.
Le FAQ pool : files, quotas et conflits complète cette lecture lorsque la gouvernance dépasse la seule couche Xcode.
SSH et isolation du trousseau : deux couches qu’il faut découpler
Le transport SSH garantit l’authenticité du canal et le chiffrement ; il ne crée pas automatiquement une cloison entre les identités de signature présentes sur la machine. Lorsque plusieurs pipelines utilisent le même utilisateur de service macOS, ils partagent le même login keychain sauf configuration contraire. Les bonnes pratiques consistent à séparer compte CI et compte humain, à verrouiller les étapes qui importent un certificat avec flock ou une file orchestrateur, et à documenter où résident les profils de provisionnement. Pour une vue d’ensemble des accès, reliez cette page au guide choix SSH et VNC et à la matrice Jump Host et certificats.
La partition trousseau peut prendre la forme d’un trousseau fichier par équipe, d’un conteneur dédié sur l’hôte, ou d’une machine de signature séparée ; le critère n’est pas la beauté de l’architecture mais la traçabilité : qui a importé quelle identité, quand, et sous quel verrou. Les équipes conformes ajoutent un identifiant de build dans les journaux à côté du hash du commit.
Tableau synthèse : transport, concurrence, file, DerivedData
Le tableau suivant condense les décisions les plus utiles en 2026 pour un petit pool ; adaptez les chiffres à votre p95 observé.
| Volet | Approche conservatrice | Approche optimisée | Signal d’alarme |
|---|---|---|---|
| SSH / session | Un compte build dédié, pas de shell interactif partagé | Jump Host + certificats courts par rôle | Même clé humaine sur runners et postes |
| Trousseau codesign | Sériel strict autour import clé et archive | Trousseaux fichiers disjoints par équipe + variables CI | Prompts graphiques bloquants en CI |
| Concurrence Xcode | Un archive lourd ; unitaires sans UI en parallèle si marge CPU | Deux jobs légers si RAM libre > huit Go et CPU < soixante-quinze % | Swap actif ou temps de linkage qui double |
| File / flock | Verrou fichier par ressource (codesign.lock) | File orchestrateur + flock -n pour sections courtes | Attente médiane file > quinze minutes |
| DerivedData | Chemin par job sous préfixe commun | Cache modules lecture seule partagé + build dir isolé | Index partagé corrompu entre branches |
Pour aligner labels GitHub Actions et files, voir la matrice runner et routage ; pour worktrees et lockfiles, la matrice Git worktree.
Feuille de paramètres : profondeur de file, timeouts job, attente verrou
Les valeurs ci-dessous servent de point de départ documenté ; remplacez-les par vos percentiles réels après deux semaines de métriques.
| Paramètre | Valeur initiale | Commentaire exploitation |
|---|---|---|
| Jobs en attente max | ~20 | Refus explicite avec message retry ou autre label |
| Timeout contrôle léger | 15–25 min | Lint, tests rapides sans compilation lourde |
| Timeout build standard | 35–60 min | Ajuster sur p95 plus marge |
| Timeout archive complète | 45–90 min | Gros monorepo ou nombreuses extensions |
flock -w dépendances | 120–300 s | Toujours inférieur au timeout du job parent |
| Alerte file médiane | >15 min | Déclencher scale ou couloir séparé signing |
Chiffres reproductibles à archiver : profondeur file observée, p95 durée codesign, espace libre disque avant et après purge DerivedData, nombre d’échecs resource busy sur verrous.
Cinq étapes pour figer la matière dans votre runbook interne
- 1Cartographier comptes macOS, trousseaux et chemins DerivedData ; interdire le partage implicite.
- 2Définir un sériel pour signature et export notarisé ; paralléliser seulement les étapes sans état graphique partagé.
- 3Encadrer flock et profondeur de file dans le YAML ou le script wrapper ; message d’échec explicite.
- 4Instrumenter timeouts orchestrateur plus courts que la somme des étapes pour détecter les blocages trousseau.
- 5Revue mensuelle : quotas disque, rotation DerivedData, corrélation incidents avec hash commit et runner.
FAQ express (lisible humain)
Peut-on mélanger accès VNC interactif et pipeline codesign sur le même nœud ?
Oui mais avec fenêtres de maintenance ou nœuds séparés : le clic utilisateur et l’agent CI qui importe une clé sont deux mondes qui partagent trop souvent le même trousseau par défaut.
Faut-il un cache DerivedData partagé en écriture ?
Non pour la plupart des petites équipes : préférez lecture seule pour modules ou pas de partage jusqu’à preuve de stabilité ; sinon verrouillez l’écriture.
Synthèse
SSH sécurise le chemin ; trousseau et DerivedData déterminent la sûreté du build. Documentez plafonds, timeouts et verrous avant d’ajouter des runners. Accès pratiques : accueil Meshmac, achat sans compte, centre d’aide, liste du blog.