← Retour au blog

Coûts de test Xcode 26 Beta en flambée ?
L'isolation des runners comme solution

Double runner self-hosted pour CI Xcode 26 beta sur Mac mini distant
Xcode 16 en prod, beta sur runner dédié—après WWDC, iOS CI = séparer les disques.

Conclusion : Pour tester Xcode 26 Beta en CI après la WWDC 26, inutile de basculer main sur macos-latest en espérant que ça tienne — la bonne approche, c'est deux couloirs Runner sur Mac distant : la production reste épinglée sur Xcode 16, la beta passe par un label dédié et un répertoire DerivedData isolé.

Trois règles non négociables : ① les jobs prod n'appellent jamais sudo xcode-select ; ② prod et beta ont des -derivedDataPath physiquement séparés ; ③ les runtimes Simulator iOS 27 sont préinstallés une seule fois sur le Runner beta, pas retéléchargés à chaque job.

Périmètre : pour le « pourquoi la CI ralentit après WWDC », voir WWDC26 iOS CI plus lent — ici, un runbook 48 h pour l'isolation des runners.

Une semaine après le 10 juin, les questions Slack deviennent opérationnelles : « Sur quel Mac installer la beta ? », « Deux Xcode sur une machine ? », « Qui est responsable si main est rouge ? » La réponse : Mac mini distant en self-hosted runner, validation beta et releases App Store strictement séparées. Pas encore de runners dédiés ? Commencez par le guide d'accélération iOS CI ; coûts et régions : TCO runners en six régions.

La WWDC 26 a livré le SDK iOS 27, les frameworks Siri AI et des contrôles Swift 6 plus stricts — le tout sur la même puce M4 qui faisait déjà tourner la CI la veille. Les équipes qui mélangent beta et production paient double : builds plus longs, pipelines instables, main bloqué par des toolchains expérimentales. L'isolation des runners n'est pas un luxe enterprise — c'est le minimum viable ops pour garder le rythme TestFlight tout en explorant iOS 27.

Les minutes macos-latest hosted explosent en saison beta : chaque job repart de zéro, retélécharge les runtimes Simulator et invalide les clés actions/cache après le saut de version Xcode. Un self-hosted sur Mac mini distant inverse la logique — le disque reste chaud, le bootstrap rétrécit, et vous payez un forfait mensuel plutôt qu'une facture à la minute pour chaque expérience beta ratée. Modélisez hosted × runs beta attendus vs TCO self-hosted ; souvent, dès ~15 builds beta par semaine, un Runner beta dédié coûte moins cher que GitHub Actions.

1) Écarter trois idées reçues : une seule machine ≠ économie

L'erreur la plus fréquente post-WWDC : installer Xcode 16 et 26 beta sur le seul Mac CI et basculer via xcode-select -s dans le workflow. Sur le papier, une location en moins ; en pratique, plus cher qu'un second runner :

  • Conditions de course : deux jobs parallèles — le second xcode-select écrase le chemin global. Un archive prod peut utiliser le compilateur beta sans que personne ne le voie dans le PR.
  • Cache contaminé : un ~/Library/Developer/Xcode/DerivedData partagé mélange les modules Swift. Erreurs fantômes : vert en local, rouge aléatoire en CI.
  • Disque et RAM : deux Xcode + deux runtimes Simulator ≈ 80 Go+. Sur 16 Go, le full build beta swap et ralentit tous les jobs, y compris ceux censés rester en Xcode 16.

Autre illusion : « On ne teste la beta la nuit, la machine est libre le jour pour la prod. » Un cron nightly et un push main à 17 h 58 entrent quand même en collision. Le scheduling CI n'est pas déterministe — les labels, si. Même logique pour les équipes Flutter : flutter build ipa sur prod-runner, probes iOS 27 sur beta — voir Flutter iOS CI pour les chemins cache par lane.

Décision en une phrase : équipe qui shippe daily sur main et tient TestFlight → runners prod et beta isolés obligatoires. Seules les petites équipes à release mensuelle et beta nightly peuvent envisager le partage — avec DerivedData séparés quand même.

2) Architecture dual-runner : pools de labels et split des workflows

Architecture minimale viable : deux Mac mini M4 distants — ou un abo prod mensuel + machine beta à la location journalière pendant l'adaptation iOS 27 :

RunnerLabel GitHubVersion XcodeJobs concernés
Prod Aself-hosted, macos, ios-prodXcode 16.4 (figé)archive main, TestFlight, tags release
Beta Bself-hosted, macos, xcode26-betaXcode 26 betabranches ios-27-*, nightly adaptateur, sondes API

Split côté workflow via runs-on — les branches beta ne doivent jamais déclencher le label ios-prod :

.github/workflows/ios-prod.yml — couloir production
name: iOS Production CI
on:
  push:
    branches: [main, release/*]
jobs:
  archive:
    runs-on: [self-hosted, macos, ios-prod]
    env:
      DEVELOPER_DIR: /Applications/Xcode_16.4.app/Contents/Developer
      DERIVED_DATA: /var/ci/deriveddata/prod
    steps:
      - uses: actions/checkout@v4
      - name: Build & Archive
        run: |
          xcodebuild -scheme MyApp -configuration Release \
            -derivedDataPath "$DERIVED_DATA" \
            -archivePath build/MyApp.xcarchive archive
.github/workflows/ios-beta.yml — couloir beta
name: iOS 27 Beta Adapter
on:
  push:
    branches: [ios-27-*, feature/siri-ai-*]
  schedule:
    - cron: '0 2 * * *'
jobs:
  beta-build:
    runs-on: [self-hosted, macos, xcode26-beta]
    continue-on-error: true
    env:
      DEVELOPER_DIR: /Applications/Xcode_26_beta.app/Contents/Developer
      DERIVED_DATA: /var/ci/deriveddata/beta
    steps:
      - uses: actions/checkout@v4
      - run: xcodebuild -scheme MyApp -sdk iphonesimulator build \
          -derivedDataPath "$DERIVED_DATA"

Les labels sont un contrat ops. Enregistrement : documentation GitHub self-hosted. Webhooks : FAQ OpenClaw CI Runner.

3) Installer Xcode 26 beta sur Mac distant et faire coexister les versions

Sur bare metal distant, deux Xcode côte à côte dans /Applications, noms de dossiers explicites pour que la beta n'écrase pas la stable :

  1. Télécharger Xcode 26 beta (.xip) depuis Apple Developer Downloads, extraire en SSH vers /Applications/Xcode_26_beta.app.
  2. Runner prod : uniquement DEVELOPER_DIR en chemin absolu dans le workflow — pas de sudo xcode-select -switch dans les jobs.
  3. xcodebuild -runFirstLaunch et acceptation licence une fois manuellement — pas à chaque job CI.
  4. Runtime Simulator iOS 27 préinstallé sur la machine beta ; retirer -downloadPlatform des workflows.

Développeurs locaux en double version : voir Xcode lent ? Mac mini cloud — écrire en local, compiler lourd sur M4 cloud. Pourquoi Simulator/Instruments exigent macOS : toolchain Xcode macOS only.

4) DerivedData / Pods / SPM — triple isolation de cache

L'invalidation post-WWDC vient du changement de format compilateur/module, pas d'un cache « cassé ». Stratégie :

Tableau : prod vs beta — chemins persistants entre jobs
Type cacheChemin prodChemin betaNote
DerivedData/var/ci/deriveddata/prod/var/ci/deriveddata/beta-derivedDataPath figé
CocoaPods/var/ci/cocoapods/prod/var/ci/cocoapods/betaCP_HOME_DIR
SPM/var/ci/spm/prod/var/ci/spm/betaclonedSourcePackagesDirPath
ModuleCachesous arbre prodarbre beta séparéne pas partager ~/Library

actions/cache suffit rarement en saison WWDC : clés invalidées après major Xcode ; transfert de Go de DerivedData souvent plus lent que disque local. La valeur self-hosted : disque persistant — le 2ᵉ build beta passe de 20+ à ~10 min. Cache triple Flutter : Flutter iOS CI ; signature TestFlight : guide self-hosted (Fastlane/Match détaillés).

Init runner (une fois)
sudo mkdir -p /var/ci/{deriveddata,cocoapods,spm}/{prod,beta}
sudo chown -R $(whoami) /var/ci
du -sh /var/ci/deriveddata/*

5) Pièges classiques : crash beta, SDK gonflé, keychains mélangées

  • Beta rouge bloque merge : continue-on-error: true ; jamais required check sur beta.
  • Prod utilise SDK beta : vérifier DTXcode et DEVELOPER_DIR dans les logs archive.
  • Keychain / Match : keychain login séparée par runner ; git_url Match partageable, mot de passe keychain par machine. Matrice support Xcode Apple.
  • Disque plein : SSD 512 Go sur beta ; cron hebdo supprime sous-dossiers beta > 14 jours.
  • Archive parallèle OOM : M4 16 Go — concurrency prod = 1.
  • Branch protection trop stricte : checks required qui ne distinguent pas beta/prod — définir statuts séparés par label.
  • Flutter + natif : flutter build ipa et xcodebuild ne partagent pas DerivedData aveuglément — voir Flutter iOS CI.

Tenez un runbook d'une page : quelle machine porte quel label, qui met à jour Xcode beta, procédure rollback si un build beta touche la keychain prod. Moins cher qu'un week-end de debug « CI vert local, rouge remote ».

6) Exemple : P50 avant/après split runner (pas un SLA)

MétriqueSans split (main en beta)Isolation dual-runner
P50 archive main~42 min~11 min
P50 adaptateur beta(concurrence prod)~22 min S1, ~12 min S2
Échecs main par betaélevé~0
Nombre de Mac12× M4 ou prod + location beta

Benchmark 48 h sur votre dépôt. Métrique clé : main ne paie plus pour la beta. Observez aussi la variance P50–P95 sur main — moins d'alertes « 11 min hier, 38 aujourd'hui ».

7) Checklist mise en œuvre 48 h

  1. J0 matin : figer Xcode prod, DEVELOPER_DIR dans workflow prod.
  2. J0 aprem : Mac mini distant (location 48 h) enregistré xcode26-beta.
  3. J1 : créer /var/ci/... ; premier full build beta ; prod inchangée.
  4. J2 : beta en nightly + branches ios-27-* ; retirer check beta des protections.
  5. Validation : trois archives main < 15 min ; beta rouge sans @channel Slack.

Deuxième machine en mensuel ? Spike beta en journalier d'abord — TCO : MacBook Pro vs Mac cloud et TCO six régions.

8) Questions fréquentes (15)

1. Deux Xcode sur un Mac distant ? Oui — dossiers .app distincts ; CI via DEVELOPER_DIR.

2. Beta runner 24 Go RAM ? 16 Go M4 suffit souvent ; archives multi-target parallèles → 24 Go.

3. Prod lance parfois jobs beta ? Déconseillé — DerivedData séparé minimum ; machines séparées mieux.

4. macos-latest remplace un runner beta ? Non — disque éphémère, bootstrap 15+ min en saison WWDC.

5. actions/cache suffit ? Clés invalidées après major Xcode ; transferts lents vs disque local.

6. Beta instable, CI tout rouge ? Attendu — lane beta optionnelle.

7. Vérifier prod sans compilateur beta ? DTXcode ou assertion DEVELOPER_DIR.

8. Runtime Simulator chaque job ? Non — préinstallé une fois sur beta.

9. Runners régions différentes ? Oui — prod près de l'équipe.

10. OpenClaw pour beta ? FAQ OpenClaw CI.

11. Location journalière suffit ? Pour spike adaptation oui ; nightly long terme → mensuel.

12. Nettoyer DerivedData quand ? Lane > 40 Go — beta d'abord.

13. Swift 6 strict ? Uniquement lane beta ; prod migration progressive.

14. Lien avec l'article WWDC ? Celui-ci explique le pourquoi ; celui-ci le comment isoler.

15. Deux machines en 48 h obligatoires ? Non — sans beta sur main, prod seul ; lane beta quand location prête.

La beta peut expérimenter — la prod doit rester stable

Post-WWDC 26, la config la plus rentable est souvent un runner prod mensuel + une machine beta à la demande : Mac mini M4 7×24 pour TestFlight, beta en location journalière pour l'adaptation iOS 27. Nuvcloud bare metal — DerivedData survit aux jobs ; M4 16 Go suffit à la plupart des archives iOS, 24 Go pour schemes parallèles. Silencieux, faible consommation, CI sans surveillance.

Vous planifiez Xcode 26 Beta CI sans faire de main un laboratoire ? Nuvcloud Mac mini M4 cloud est le point de départ le moins cher voir les tarifs , séparer beta et prod en 48 h.

LIMITED Tarifs