Ce que vous cherchez probablement
- Runner macOS GitHub Actions lent / bloqué en
Queued - Build iOS CI en échec ou retries en boucle
- Build Xcode timeout en CI mais OK en local
- Cloud Mac vs GitHub Actions : que choisir ?
- Pipeline CI instable, résultats non reproductibles
Si vous maintenez GitHub Actions ou des runners macOS auto-hébergés, les plaintes les plus fréquentes en 2026 sont très concrètes : files d'attente plus longues, temps de compilation Xcode instables, retries répétés par PR, CI tantôt vert tantôt rouge. Cet article déploie quatre couches — d'abord les symptômes d'ingénierie, puis comment les agents « bouclent » le CI, enfin le rôle du Cloud Mac. Le titre « Le CI est mort » est traité en FAQ à la fin ; le corps du texte part des pannes que vous reconnaissez immédiatement.
1 · Première couche : pourquoi GitHub Actions semble « plus lent, instable, flaky » en 2026
Sur les six derniers mois, les équipes iOS, Flutter et macOS nous remontent le même schéma — pas « le CI est un concept dépassé », mais l'accumulation simultanée des quatre problèmes ci-dessous.
1.1 File d'attente des runners macOS
Sur les runners hébergés macos-latest, le temps en Queued dépasse souvent le temps de build réel. Timeline du job : 40 minutes d'attente, 12 minutes d'exécution — l'équipe optimise encore les flags xcodebuild. La formule de diagnostic reste wait time >> run time, détaillée dans le runbook file d'attente macOS. En 2026, les queues s'allongent car le plafond de concurrence macOS ne suit pas le nombre de jobs — et les jobs Archive / lourds occupent les slots, entraînant le feedback rapide des PR dans la même file.
1.2 Variance des temps de build Xcode
Même commit relancé : en CI, compilation Xcode parfois 18 minutes, parfois 31, Mac local stable autour de 15. Facteurs courants : cold start du runner, cache DerivedData manqué, CocoaPods re-résolu, patch Xcode de l'image différent du poste local. Vu isolément, cela ressemble à un « mauvais cache » — mais quand chaque retry part en environnement froid, la variance devient « le CI n'est pas fiable ».
1.3 Retries hors de contrôle
Outre le retry-on-failure explicite dans les workflows, les retries implicites se multiplient : agent ou bot lit les logs → patch → push → re-déclenche Actions. Une PR passe de « 2 push humains » à « 8 push machine » ; facture minutes et pression sur la queue montent ensemble. Vous suspectez des tests flaky — en réalité la même PR tourne en CI avec du code différent à chaque tour.
1.4 CI flaky : vert puis rouge, difficile à reproduire
Classique : timeouts de tests sporadiques, échec de démarrage simulateur, keychain de signature bloqué. En 2026 s'ajoute une couche : chaque tour d'agent produit un diff différent — difficile de trancher « test flaky ou fix cassé ». La phrase qui fait mal aux release engineers : « Hier soir le CI était vert, ce matin le même tag est rouge. »
| Ce que vous voyez | Souvent pris pour | À vérifier d'abord |
|---|---|---|
| Job longtemps en Queued | Panne GitHub | Concurrence macOS, Archive en PR ? |
| Temps Xcode instable | Projet qui grossit | Cache, image Xcode, cold start |
| Plusieurs runs par PR | Pushes désordonnés | Retry agent/bot, concurrency absent |
| Vert puis rouge | Mauvais tests | Commit cohérent par tour ? environnement qui dérive ? |
2 · Deuxième couche : pas « le CI a empiré », mais le CI a été bouclé
Corriger queue, cache et tests séparément ne soulage souvent qu'un tour. Ensemble, une ligne commune apparaît : le CI n'est plus une vérification unique, mais une boucle « échec → correctif → relance ». Avant les agents, cette boucle vivait dans la tête des ingénieurs ; aujourd'hui elle est dans l'infrastructure — le modèle lit les logs, produit des patches, déclenche les workflows.
La chaîne typique est déjà banale :
- PR ouverte → CI rouge (test / build)
- Agent lit les logs Actions → commit de fix
- Push → nouveau workflow → peut-être encore rouge → nouveau fix
- Jusqu'au vert — ou jusqu'à arrêt humain / tokens épuisés
Officiellement c'est encore GitHub Actions / CI ; en pratique c'est une boucle de retry agent. Vous ne combattez plus « un build raté », mais le résultat probabiliste de plusieurs tentatives — d'où les symptômes de la couche 1 : queue saturée par les jobs multiples, temps Xcode qui dérive par cold starts, flakiness car code et environnement changent à chaque tour.
Un cadre un peu abstrait mais actionnable : le CI classique suppose un flux déterministe — même commit, même environnement, résultat reproductible. Après la boucle agent, le chemin devient probabiliste — quel essai passe au vert, combien de commits intermédiaires, Archive déclenché par erreur. Cela explique pourquoi « ajouter du cache » ne règle pas tout.
| Dimension | CI classique (vérif unique) | CI bouclé (agent retry loop) |
|---|---|---|
| Nombre de déclenchements | Peu, poussés par l'humain | Relances auto, ×N |
| Version du code | Tête de PR stable | Commits qui évoluent dans la boucle |
| Sens du rouge | Le code actuel est défectueux | Peut-être « pas assez d'essais » |
| Coût | Minutes × tarif | Minutes + tokens + cold start |
GitHub continue d'optimiser workflows, runners et cache — au service de jobs déterministes unitaires. Quand le repo fait tourner des boucles agent par défaut, ces gains aident mais n'arrêtent pas l'effet multiplicateur « nombre de jobs × tours de retry ». D'où le titre « GitHub ne l'a pas vu » : le récit produit reste CI/CD, l'usage dérive vers un correcteur automatique en boucle.
3 · Troisième couche : le changement structurel — de pipeline CI à retry loop + substrat d'exécution
Symptômes (couche 1) et cause (couche 2) alignés : le CI passe d'un pipeline linéaire à un système d'exécution avec rétroaction.
Fig. 1 · CI bouclé : décision agent + exécution runner + boucle de feedback
Ancien modèle : Code → Build → Test → Result — un échec arrête la ligne. Nouveau : Code → Agent → Modify → Execute → Retry → … → Result — l'échec fait partie de la boucle, pas la fin. La coche verte sur GitHub rassure encore, mais le sens change — peut-être vert au quatrième essai, avec des commits modifiés entre-temps.
Un terme nouveau mais très ingénieur : execution substrate (substrat d'exécution) — l'agent peut modifier le code, mais compiler, signer et uploader doivent aboutir sur une surface macOS stable et reproductible. Les jobs serverless sont trop courts, l'état ne suit pas ; le Mac local dort et met à jour Xcode ; les runners hébergés font la queue et dérivent en spec. Le Cloud Mac comble cette couche : en ligne en continu, toolchain épinglable, environnement snapshot-able — pas un « bureau à distance », mais la strate du retry loop qui doit rester aussi déterministe que possible.
Le pouvoir d'exécution se déplace : avant l'humain écrivait le workflow, la machine exécutait ; maintenant l'humain trace les frontières (PR vs Archive, max retries), l'agent explore dans ces limites, l'humain valide le résultat final. Les équipes macOS/iOS y sont sensibles — signature et Archive ne doivent pas se répéter sans fin dans la boucle, sinon vert ≠ prêt pour release.
4 · Quatrième couche : stabiliser la surface d'exécution avec Cloud Mac (action immédiate)
Inutile d'attendre le nouveau récit GitHub ni d'abandonner Actions. Contre le CI bouclé, chez VPSSpark ces quatre actions se vérifient le plus souvent — et c'est ce qui différencie Cloud Mac des runners hébergés.
4.1 Pools séparés : limiter le rayon des retries
Les PR ne font que L0/L1 (analyze, tests unitaires, build simulateur), pas d'Archive en PR ; release, IPA et notarisation uniquement sur pools isolés main/tags. Même une boucle agent agressive : un Archive de 35 minutes ne sature pas le pool rapide ni ne met toute l'équipe en Queued. Règles strictes dans l'article CI Hard Rules ; topologie double pool Flutter dans 2 Cloud Mac fast/archive.
4.2 Warm environment : pas de cold start à chaque retry
Persister PUB_CACHE, DerivedData, cache téléchargement Pods ; runner autostart, en ligne 7×24. Au 2ᵉ retry agent, pas de pod install de 15 minutes — sinon la variance Xcode est lue à tort comme « le projet ralentit ». Cloud Mac achète le coût de maintien d'environnement, pas seulement des minutes CPU par job.
4.3 macOS execution substrate : versions toolchain figées
Épingler Flutter/Xcode majeur via image ou fvm ; machine Archive et pool rapide isolés physiquement, pas de DerivedData partagé. Chaque tour de retry doit tourner sur le même certificat Distribution, les mêmes CLT — prérequis d'un CI iOS auditable. Limites runners auto-hébergés : documentation GitHub.
4.4 Retry isolation : plafonds sur la boucle
Niveau workflow : concurrency annule les anciens runs d'une même PR ; timeouts et nombre max de push dédiés aux triggers agent ; machine de signature réservée au pool release. Syntaxe : documentation workflow. L'objectif n'est pas d'interdire les agents, mais de tenir la boucle dans des limites contrôlées.
macos-fast ; runners hébergés pour Archive en attendant. Observer 3 jours la queue P95 et la variance wall time Xcode. Stable ? Ajouter une 2ᵉ machine Archive — comme la série « 2 machines pour démarrer », motif étendu de la file d'attente au retry agent.
5 · FAQ
« Le CI est mort », est-ce de la provocation ?
Le titre est volontairement fort, le phénomène réel : votre pipeline peut rester verte, les PR fusionner — et pourtant « même code, mêmes checks, chemin et résultat plus stables » ne tient plus. « Le CI est mort » ne signifie pas que GitHub Actions est inutilisable, mais que l'hypothèse classique — build et vérification comme processus déterministe — s'effondre quand des agents modifient le code et re-déclenchent les workflows. Plus juste : le CI vit, la sémantique a glissé — de l'intégration continue à la tentative continue.
GitHub va-t-il changer le produit pour ça ?
Oui, mais le rythme peut dépasser l'usage. Vous verrez encore optimisations workflow, capacité runner, cache — tout au service du CI classique. Les capacités agent (sandbox, audit, facturation tokens) arriveront plutôt par étapes qu'en nouveau récit du jour au lendemain. Les équipes n'ont pas à attendre la définition officielle : séparer pools PR/Archive, limiter retries, verrouiller la machine de signature — garde-fous peu coûteux à l'ère agent.
Cloud Mac vs runner macOS hébergé ?
En bref : runner hébergé = location du temps d'un job ; Cloud Mac = environnement stable sur la durée. Releases rares, queue acceptable, jobs courts — macos-latest suffit souvent. Boucle agent ou CI iOS fréquent : besoin de Xcode/certificats/cache résidents, pools rapide et Archive isolés physiquement, pas d'interruption par veille ou upgrade Xcode silencieux. Cloud Mac vaut surtout pour signature, Archive, notarisation — chaque retry sur la même clé, la même toolchain, pas la roulette du cold start.
Lien avec OpenClaw / agents locaux ?
Pas de conflit, couches différentes. OpenClaw, Cursor Agent, Copilot local gèrent quoi modifier et comment orchestrer — gateway et scheduling. Runner / Cloud Mac gèrent où et dans quel environnement compiler, tester, signer, uploader. L'agent peut patcher en local ou boucler en CI ; les builds macOS finissent sur une surface d'exécution reproductible. Séparer orchestration et exécution évite « agent malin, CI repart de zéro dans un environnement inconnu à chaque fois ».
Étape suivante couche 4 : une Cloud Mac pour figer le substrat
Si queue, dérive Xcode, explosion de retries et flakiness des trois premières couches vous parlent — la couche 4 n'a pas besoin de tout résoudre d'un coup. Chemin le plus courant : une Cloud Mac en pool rapide warm pour amortir cold start et dérive toolchain dans le retry agent ; Archive et signature isolés si besoin. Apple Silicon basse consommation convient au fonctionnement continu ; pour les équipes iOS/macOS, cela cible mieux la structure de coût du CI bouclé que des packs de minutes GitHub supplémentaires.
Si vous utilisez cet article comme checklist PoC, le VPSSpark Cloud Mac mini peut servir de point de départ en macOS execution substrate — voir les offres, stabiliser l'environnement d'abord, laisser l'agent tourner au Nᵉ essai ensuite.