Une seule machine reste souvent peu utilisée, mais la publication continue de faire attendre les tests et les archives.

La décision la plus rapide consiste à mesurer les Jobs en pointe, leur durée d’occupation et le délai acceptable : un projet peu fréquent peut commencer avec un Mac, tandis qu’un chevauchement régulier entre tests et publication justifie deux Mac ou une extension temporaire.

Cette méthode s’adresse à trois profils : le développeur indépendant qui maintient une seule application iOS avec un self-hosted runner, l’équipe qui veut faire tourner les tests de pull request en parallèle des versions TestFlight, et le responsable qui préfère louer un Mac distant pendant les périodes de publication plutôt que d’acheter une machine qui restera inactive.

01

Capacité réelle : Jobs, files et créneaux de publication

Le nombre de développeurs n’est pas une unité de capacité. Le bon niveau d’analyse est le Job GitHub Actions. Un workflow peut contenir plusieurs Jobs ; chaque Job peut, à son tour, solliciter un Runner et rester bloqué avant même que Xcode ne commence à travailler.

Nous séparons donc les éléments suivants :

  • le workflow déclenché par un commit, une pull request ou une planification ;
  • le Job qui compile, teste, archive ou publie ;
  • le Runner qui reçoit ce Job ;
  • le Mac hôte qui fournit macOS, Xcode, les certificats et les dépendances ;
  • les tâches internes à Xcode, notamment la compilation parallèle ou les tests de plusieurs appareils ;
  • le traitement côté service, par exemple l’analyse d’un paquet après son envoi à App Store Connect.

Un Runner ne doit pas être confondu avec une seconde tâche interne de Xcode. Activer davantage de parallélisme dans une compilation peut accélérer un Job, mais cela ne crée pas une seconde file d’exécution indépendante. Pour estimer la capacité, nous comptons donc les Jobs qui se chevauchent réellement et non le nombre de cibles compilées dans un même Job.

GitHub fournit plusieurs points d’observation. L’historique des exécutions permet de retrouver la durée d’un workflow et de ses Jobs ; les indicateurs Actions apportent une vue plus globale ; l’événement workflow_job distingue les états queued, in_progress et completed. Ces trois états sont documentés dans les événements Webhook de GitHub. Pour un dépôt personnel qui ne dispose pas d’indicateurs d’organisation détaillés, l’export de l’historique, les journaux horodatés et un petit relevé quotidien constituent une solution de remplacement exploitable.

Attention : un temps passé à attendre App Store Connect après l’envoi ne signifie pas que le Mac est encore occupé. Il faut séparer l’occupation du Runner de l’attente côté service, sinon la capacité nécessaire sera artificiellement surestimée.

Les quatre mesures à relever

Pour chaque famille de Jobs, nous relevons :

  1. le moment de mise en file ;
  2. le début effectif sur le Runner ;
  3. la fin du travail exécuté sur le Mac ;
  4. la fréquence de déclenchement et les chevauchements observés.

Ces repères produisent deux durées différentes :

  • le délai d’attente, entre queued et in_progress ;
  • le temps d’occupation, entre le démarrage du Job sur le Mac et sa fin effective.

Les indicateurs de performance GitHub Actions servent à vérifier que ces mesures ne reposent pas uniquement sur une impression laissée par l’interface. Pour un projet sans visibilité organisationnelle, nous recommandons de conserver les identifiants de workflow, les heures de début et de fin, le résultat, le type de Job et le label du Runner. Les noms de dépôt, les identifiants d’équipe, le Bundle ID, le Team ID, les chemins locaux et les certificats doivent rester masqués dans cette feuille.

02

Décisions par charge : un Mac, deux Mac ou extension

Le tableau ci-dessous ne donne pas un nombre universel. Il relie un type de charge à une décision initiale et à une condition de révision.

Profil de charge Symptôme observé Décision de départ Condition pour changer
Indépendant, faible fréquence Les tests et l’Archive sont rarement simultanés Un Mac La file apparaît pendant les publications ou bloque les validations urgentes
Indépendant, forte fréquence Branches, tests et TestFlight se chevauchent Un Mac optimisé, puis deuxième Mac si le chevauchement persiste Les Jobs prioritaires attendent derrière des Jobs annulables
Petite équipe Plusieurs pull requests arrivent dans le même créneau Deux environnements logiquement séparés ou deux Mac selon les mesures Le délai de retour dépasse l’objectif de l’équipe
Plusieurs applications Tests quotidiens et fenêtre de publication commune Capacité de validation distincte de la capacité de publication Une maintenance empêche de publier ou les labels mélangent les risques
Publication saisonnière Le pic est concentré sur quelques jours ou semaines Mac supplémentaire pendant la période concernée L’extension est requise presque en permanence

Projet indépendant à faible fréquence

Une seule machine suffit généralement lorsque les validations ordinaires, les tests planifiés et l’Archive officielle peuvent être ordonnés sans se bloquer. Cette conclusion ne repose pas sur le fait que le projet est « petit ». Elle repose sur l’absence de chevauchement problématique dans les données.

Nous plaçons les Jobs dans des niveaux de priorité distincts :

  • validation rapide sur chaque pull request ;
  • tests plus lourds selon un calendrier ;
  • Archive et envoi vers TestFlight sur une voie réservée.

Le but n’est pas de maintenir le Runner occupé en permanence. Un faible taux d’utilisation moyen peut être parfaitement rationnel si la file reste courte au moment où une décision doit être prise.

Une seule machine peut-elle exécuter plusieurs Jobs iOS en même temps ? Elle peut recevoir plusieurs demandes dans un workflow global, mais la capacité de Runner doit être comptée comme une unité d’exécution à la fois pour chaque environnement. Le parallélisme interne de Xcode et la concurrence entre Jobs sont deux sujets différents. Si deux Jobs doivent progresser simultanément, il faut vérifier la présence de deux environnements capables de les recevoir, puis valider l’isolation des certificats et du cache.

Avant de louer une seconde machine, nous éliminons les faux signaux :

  • téléchargement répété des dépendances ;
  • scripts qui réinstallent inutilement les outils ;
  • tests identiques exécutés par plusieurs workflows ;
  • matrice de simulateurs plus large que le besoin de validation ;
  • archive lancée alors qu’une autre archive obsolète est déjà en file.

La documentation Apple sur le temps de compilation Xcode aide à distinguer une compilation intrinsèquement lente d’une attente causée par la file GitHub Actions.

Projet indépendant à forte fréquence

Le cas difficile est celui du développeur seul qui travaille sur plusieurs branches, lance des tests automatisés et produit fréquemment des versions TestFlight. La moyenne quotidienne peut rester faible alors que plusieurs Jobs se présentent dans un même créneau.

Nous comparons alors trois actions, dans cet ordre :

  1. modifier le workflow pour éviter les tâches devenues obsolètes ;
  2. séparer les validations rapides des tests et des Archives ;
  3. ajouter un second environnement si les Jobs prioritaires restent régulièrement en attente.

La concurrence GitHub Actions permet notamment d’annuler ou de remplacer certains travaux obsolètes. Les règles de concurrence des workflows sont utiles pour une branche où seul le dernier commit mérite une validation complète. En revanche, une Archive déjà destinée à TestFlight ne doit pas être annulée comme une simple vérification de pull request.

Un second Mac apporte surtout de la simultanéité et un retour arrière en cas de panne. Il ne rend pas automatiquement un Job individuel plus rapide. Pour accélérer un Job unique, il faut examiner le cache, les dépendances, la configuration Xcode, les tests et le stockage. Pour empêcher une publication de bloquer les tests, il faut examiner le routage et la capacité.

03

Petite équipe : délai de retour et séparation des risques

Pour une petite équipe, nous ne cherchons pas à supprimer toute attente. Nous définissons d’abord le délai acceptable pour chaque classe de travail :

  • contrôle de compilation et tests ciblés ;
  • tests sur simulateur ;
  • Archive et signature ;
  • envoi vers App Store Connect.

Ces classes n’ont pas la même priorité et ne doivent pas nécessairement partager le même Runner. Les règles de sélection d’un Runner pour un Job permettent d’orienter les tâches à l’aide de labels. Les labels des self-hosted runners doivent refléter une capacité vérifiable, et non une promesse vague comme « rapide ».

Nous pouvons par exemple distinguer :

  • un label de validation pour les pull requests ;
  • un label de test avec simulateurs et données de test ;
  • un label de publication avec accès aux secrets nécessaires.

La seconde séparation est logique, pas uniquement matérielle. Deux labels sur le même Mac ne créent pas deux capacités. À l’inverse, deux Mac portant le même label peuvent recevoir des Jobs interchangeables, à condition que Xcode, les certificats, les profils et les dépendances soient réellement alignés.

Les tests iOS et l’Archive doivent-ils utiliser des Mac différents ? Pas systématiquement. Ils doivent être séparés lorsque la publication doit rester possible pendant une vague de tests, lorsque les secrets de signature exigent une restriction particulière, ou lorsqu’une maintenance de l’environnement de test ne doit pas interrompre une livraison. Une seule machine reste acceptable si les données montrent que les créneaux sont distincts et qu’un scénario de reprise a été vérifié.

Apple recommande d’examiner les résultats de test et leurs détails dans la documentation consacrée à l’exécution et l’interprétation des tests Xcode. Cette distinction est importante pour une équipe qui produit aussi des applications audio, vidéo ou de design : les tests de ressources, les fichiers volumineux et les outils de génération peuvent occuper le Mac sans avoir le même poids qu’une Archive de publication.

04

Plusieurs applications : capacité en couches

Lorsque plusieurs dépôts partagent des Mac, la capacité doit être organisée par risque et par usage. Nous ne faisons pas entrer tous les workflows dans une file unique portant un label générique.

La couche de validation accueille les compilations et les tests qui peuvent être relancés. La couche de publication conserve les certificats, les profils, les accès App Store Connect et les procédures de reprise. Entre les deux, nous documentons le propriétaire du workflow, le chemin de sortie et la règle d’annulation.

Modèle d’exploitation Capacité permanente Renfort pendant la publication Critère d’arrêt
Base partagée Un socle commun pour les validations Ajout temporaire lors d’un pic La publication reste indépendante et récupérable
Base séparée Validation et publication sur des environnements distincts Renfort uniquement si la file dépasse l’objectif Les coûts d’une capacité inactive deviennent supérieurs au gain
Publication autonome Mac réservé aux Archives et aux envois Renfort éventuel pour les tests La procédure de secours est validée sur un environnement distinct

Le routage ne doit pas exposer les secrets de publication à tous les Jobs. Les variables d’environnement, certificats, profils de provisioning, clés privées et chemins de trousseau doivent être vérifiés séparément. Le fait qu’un Runner soit en ligne ne prouve pas qu’il est prêt à publier.

Pour les versions destinées à App Store Connect, le traitement après l’envoi ne doit pas être inclus dans le temps d’occupation du Mac. Les étapes d’upload et les informations attendues sont précisées dans la documentation Apple sur l’envoi des builds à App Store Connect. Nous conservons toutefois un contrôle distinct pour confirmer qu’une version a bien été reçue et traitée.

Est-il préférable d’ajouter un Mac distant uniquement pendant les publications ? Oui, lorsque le pic est concentré sur une période identifiable et que les validations ordinaires restent fluides le reste du temps. Non, si la file réapparaît chaque jour ou si l’ajout temporaire prend trop de temps à configurer. La bonne réponse dépend du délai de livraison de l’environnement, de la stabilité du toolchain et de la capacité à restaurer les certificats sans intervention improvisée.

05

Feuille de décision et validation opérationnelle

Nous utilisons la feuille suivante avant de commander une capacité supplémentaire. Chaque case doit être accompagnée d’un lien vers une exécution, un journal ou un test de reprise.

  • [ ] Relever séparément l’attente en file et le temps d’occupation du Mac.
  • [ ] Compter les Jobs qui se chevauchent réellement pendant le pic.
  • [ ] Distinguer compilation, tests, Archive, signature, upload et traitement App Store Connect.
  • [ ] Identifier les Jobs annulables et les Jobs qui doivent toujours aller au bout.
  • [ ] Vérifier les labels, le routage et le nombre réel de Mac correspondant à chaque label.
  • [ ] Mesurer l’effet des dépendances téléchargées plusieurs fois et des scripts redondants.
  • [ ] Tester une pull request pendant une Archive sans exposer les secrets de publication.
  • [ ] Débrancher ou redémarrer le Mac principal, puis confirmer la reprise du Runner.
  • [ ] Vérifier qu’un second Mac possède la même version de Xcode, les mêmes outils et les mêmes chemins attendus.
  • [ ] Définir le seuil qui déclenche une location temporaire et celui qui autorise son arrêt.
  • [ ] Consigner les noms de dépôt, identifiants, certificats et chemins sous forme anonymisée.

Cette vérification répond aussi à la question centrale du dimensionnement : le nombre de Runners doit augmenter lorsque plusieurs Jobs importants doivent progresser en parallèle, pas simplement parce que plusieurs personnes ont accès au dépôt.

Pour un premier environnement, nous pouvons consulter les options de Mac distant de MESHLAUNCH, puis comparer la durée de location avec la période réelle du pic. Les projets qui ont besoin d’un environnement macOS stable pour un travail créatif complémentaire — montage vidéo, traitement audio ou génération d’éléments graphiques — doivent aussi vérifier la continuité de l’accès interactif, et pas seulement la réussite d’une commande CI. Une configuration Mac mini destinée aux tâches de développement peut servir de point de comparaison, sans remplacer les mesures propres au dépôt.

06

Conclusion opérationnelle : capacité à conserver ou à louer

Pour un projet indépendant à faible fréquence, nous conservons un Mac tant que les Jobs prioritaires ne forment pas une file durable. Pour un développement intense, nous commençons par annuler les validations obsolètes et séparer les workflows ; si les tests et les Archives se disputent encore le même environnement, nous ajoutons un second Mac. Pour une petite équipe ou plusieurs applications, nous séparons la capacité de validation de la capacité de publication et réévaluons la file à partir des historiques réels.

Un Mac local acheté reste pertinent si la charge est permanente, si une interface physique est indispensable ou si l’équipe doit conserver le matériel pendant une longue période. En revanche, un seul Mac permanent devient un mauvais compromis lorsque la demande augmente uniquement pendant les tests de release, une campagne TestFlight ou une fenêtre de publication. Il immobilise du capital, conserve une machine inutilisée hors période de pointe et impose à l’équipe de gérer elle-même la panne, le remplacement et l’accès distant.

Dans ce cas, louer chez MESHLAUNCH un Mac distant pour la période de surcharge peut fournir une seconde voie d’exécution et un environnement de reprise sans acheter immédiatement du matériel dormant. La décision doit être prise après la feuille de capacité : si le manque ne survient que pendant les tests ou la publication, une location hebdomadaire ou mensuelle peut suffire ; si la file reste élevée en permanence, il faut plutôt revoir l’architecture et le coût total d’une capacité durable.