← Retour au journal

Fastlane et double Mac cloud : 3 échecs fréquents après séparation build / upload

Runbook · 2026.06.04 · ~8 min · à coller dans le runbook d'astreinte

Deux Mac cloud : archive à Hong Kong, upload Fastlane au Canada

Vous êtes d'astreinte avec au moins deux Mac cloud loués et Fastlane pour iOS, et vous voyez des logs de compilation verts sans nouveau build TestFlight (ou le mauvais paquet). Pas encore décidé pour le cloud ou un second Mac ? Lisez d'abord le Mac dédié TestFlight ou déporter les builds Xcode — ici on suppose déjà une machine compile, une autre envoie.

À la fin, vous devriez savoir : ① si les logs pointent vers certificat, artefact ou réseau ; ② si les rôles des deux Mac sont corrects et s'il faut ajouter du matériel.

Termes utilisés ci-dessous
  • Machine de build : compile dans Xcode et exporte uniquement le paquet d'installation (.ipa)
  • Machine d'upload : signe avec le certificat de distribution et envoie le .ipa vers TestFlight ; l'IP de sortie enregistrée chez Apple doit être celle de cet hôte seul

Vous pouvez passer si : vous n'avez qu'un Mac, ou TestFlight fonctionne et vous n'avez pas encore séparé « build + upload ». Si plusieurs Mac cloud et pipeline en panne : continuez.

TL;DR (30 secondes)
Après un split dual cloud Mac, le goulot est rarement le CPU mais trois erreurs de frontière Fastlane :
  1. Frontière certificat — le certificat de release a été synchronisé sur la machine de build, la machine d'upload ne peut pas signer (le plus grave)
  2. Frontière artefact — .xcarchive transféré entre DC au lieu d’une .ipa vérifiable (la plus discrète)
  3. Dérive d’identité réseau — whitelist ASC encore sur l’ancienne IPv4 upload (la plus pénible)
Ci-dessous : arbre de triage 30 s, puis les trois modes d’échec ; en fin : tableau d’acceptation, quatre stades CI et un bloc « verdict final » suffisant pour décider.

Contexte (1 min) : avec deux Mac, ce qui casse, ce sont les frontières

Beaucoup d'équipes louent deux Mac cloud : l'un près de l'Asie compile l'app en paquet le jour ; l'autre au Canada remet le paquet à Apple (TestFlight / App Store). Le second Mac vise la vitesse — mais l'astreinte souffre quand les deux touchent aux certificats et aux fichiers : build OK, TestFlight sans nouvelle version.

Découpe recommandée : modèle A (build = paquet, upload = publication)

En une phrase : la machine de build ne produit que l'.ipa ; seule la machine d'upload gère certificats et TestFlight. Ne lancez pas match sur les deux.

Dual cloud Mac roles (Model A)
Role Machine de build (Hong Kong) Example: APAC daytime builds Machine d'upload (Canada) Fixed IP for Apple
Do
Do not
Hand offPackage file + build ID (RUN_ID)None (endpoint is App Store Connect)

Les deux runners sont des Mac mini Hashvps dédiés — pour IP fixe + isolation des rôles (IP upload dans ASC, pas l’IP build). Spécifications Hong Kong : location Mac mini Hong Kong. Verrouiller l’identité upload ASC avant d’ajouter des runners build.

Build · pas de match Upload · signature exclusive build → export .ipa no certs · no upload includes build ID certs + TestFlight upload fixed public IP registered in ASC .ipa → Unité minimale inter-DC : IPA signable, pas xcarchive
Modèle A : match et signature uniquement sur upload ; build livre l’IPA

Les deux runners sont des Mac mini Hashvps dédiés — pour IP fixe + isolation des rôles (IP upload dans ASC, pas l’IP build). Spécifications Hong Kong : location Mac mini Hong Kong. Verrouiller l’identité upload ASC avant d’ajouter des runners build.

Erreur fréquente : modèle B (les deux « aident »)

Le modèle B, c'est des rôles non séparés — notre première semaine. En surface deux machines, en pratique :

  • Les deux exécutent match → clé privée de release sur le build → l'upload ne signe pas → TestFlight en échec
  • Build rsync .xcarchive → second export upload, SHA différent → mauvais artefact, Invalid Binary
  • Double export_ipa → deux ExportOptions.plist qui dérivent → upload OK, build non promouvable

Si une ligne correspond à votre workflow, un troisième Mac n’aide pas — il faut le role split build/upload (modèle A), pas plus de runners.

Observabilité : prouver le même build des deux côtés

L'incident le plus courant : « on a uploadé l'IPA d'hier ». Les mêmes champs dans les logs build et upload :

  • RUN_ID (ex. hk-build-88421)
  • GIT_SHA (commit court)
  • chemin artefact + SHA256 (build/manifest.json)
Build OK · upload OK (même RUN_ID)
# Hong Kong · build · build
[15:11:42]: Successfully exported: ./build/MyApp-20260604-1502.ipa
[15:11:42]: RUN_ID=hk-build-88421  GIT_SHA=a3f91c2  SHA256=9f2a…

# Canada · upload · upload
[02:22:01]: RUN_ID=hk-build-88421  GIT_SHA=a3f91c2  ipa_sha256=9f2a…
[02:24:18]: Successfully uploaded package to App Store Connect

Règle d’astreinte : RUN_ID upload ≠ build → traiter comme erreur d’artefact avant ASC.

Triage 30 s : pas de nouveau build TestFlight ?

Ne pas lire tout le log. Une branche de l’arbre suffit pour ouvrir le bon chapitre (à bookmarker dans le runbook) :

Arbre de triage (copier dans le runbook)
Pas de nouveau build TestFlight ?
 ├─ RUN_ID upload ≠ build (ou pas de manifest)
 │     → piège 2 · frontière artefact
 ├─ Log : match / AppStoreDistribution / code signing identity
 │     → piège 1 · frontière certificats
 └─ Upload « réussi », ASC vide / 403 / Invalid Binary (build tout vert)
       → piège 3 · dérive d’identité réseau
Trois échecs · référence rapide (astreinte)
Mode Mots-clés log (grep) Impact release
Piège 1 certificats AppStoreDistribution, No matching provisioning, match failed Bloquant : TestFlight / Store arrêtés
Piège 2 artefact RUN_ID incohérent, Invalid Binary, conflit export_method Élevé : mauvais build ou pas de promote
Piège 3 identité 403, upload OK sans processing, limites réseau ASC Intermittent : effet « hasard »

Trois modes d’échec (détail)

Piège 1 : mauvaise frontière certificats

30 s : archive build verte ; upload rouge sur match / signing.

Log : AppStoreDistribution, Could not find a matching code signing identity, No matching provisioning profiles.

Release : bloquant — TestFlight et App Store jusqu’à ce que la clé privée ne soit que sur upload.

Symptôme : archive OK côté build, lane upload en échec ; TestFlight sans nouveau build.

Log type
Could not find a matching code signing identity for type 'AppStoreDistribution'
❌  Lane upload failed

Cause : modèle B — le build exécute encore match(appstore), clé Distribution absente de l’upload.

Correctif : retirer tout match du build ; upload exclusif (rotate uniquement là, fenêtre dédiée). Voir match readonly.

Piège 2 : mauvaise frontière artefact

30 s : comparer RUN_ID et ipa_sha256 build vs. upload ; ou ASC Invalid Binary sans erreur signing sur le build.

Log : RUN_ID différent, Invalid Binary, double export_ipa / ExportOptions.

Release : élevé — ancien commit, mauvais build ou processing bloqué ; pipeline peut rester verte.

Cause : .xcarchive entre DC ou double export. Unité minimale inter-DC : IPA avec SHA, pas le dossier archive.

Correctif : un seul export_ipa + manifest.json sur le build ; upload = upload_to_testflight seulement.

Piège 3 : dérive d’identité réseau

30 s : Fastlane annonce un upload réussi ; signing vert partout ; TestFlight vide ou ASC 403.

Log : 403, Successfully uploaded sans build, refus réseau ASC malgré logs build verts.

Release : intermittent — parfois ça passe, parfois non.

Cause : IPv4 upload ≠ whitelist ASC (troisième classe silencieuse).

Correctif : quotidien sur upload : curl -4 ifconfig.me vs. ASC ; drift → whitelist + alerte.

Comment savoir que le split est réel

Checklist fusionnée — une semaine après le déploiement, chaque ligne doit être « oui » sans débat :

Acceptation dual Mac (modèle A)
Contrôle Attendu
RUN_ID alignéLogs export build et upload upload : RUN_ID, GIT_SHA, ipa_sha256 identiques
Build sans DistributionSur le build, trousseau/logs jamais AppStoreDistribution ni step match
Upload = distribution seuleLane upload : uniquement match (ou resign) + upload_to_testflight, pas ARCHIVE SUCCEEDED
Forme artefactEntre DC : .ipa + manifest (< 200 Mo) ; pas de rsync .xcarchive
Identité ASCIPv4 upload courante = whitelist ASC ; IP build absente d’ASC
Isolation runnersLabels role=ios-build-hk et role=ios-upload-ca, chaîne needs

Stade d’évolution : où en êtes-vous ?

L’incident répond à « cette nuit » ; le stade à « la semaine prochaine, changer l’architecture ? ». Quatre stades — maintenir, corriger ou imposer le role split. Beaucoup passent du stade 1 à deux Mac sans labels et atterrissent au stade 2 ; ce texte mène au stade 3 avec acceptation mesurable.

Stade 1 : un Mac, une Fastlane

Signes : un runner ; match, build, upload dans le même Fastfile. Optimiser disque, Derived Data et facturation GitHub Actions avant un second nœud build.

Conclusion : pas besoin de dual Mac. Lenteur APAC seule → ajouter un nœud build, ne pas scinder l’upload en premier.

Stade 2 : deux Macs sans role split (modèle B)

Signes : deux+ runners ; plusieurs exécutent match / export / upload ; logs avec les trois frontières de cet article. Souvent parce que « chaque Mac doit tout faire un peu » — c’est ce qui crée la dérive ; le stade 3 impose labels et chaîne needs clairs.

Conclusion :Un troisième Mac ne résout rien, augmente la dérive certificats/artefacts. Étape suivante : modèle A, pas plus de runners.

Stade 3 : role split (modèle A · cible)

Signes : build/upload séparés ; entre DC seulement IPA + RUN_ID ; match uniquement sur upload ; IP upload fixe.

Conclusion : ✔ checklist stable → scaler les runners build ou durcir l’upload. IP fixe et nœuds : offres Hashvps (verrouiller l’IP ASC upload avant d’étendre le build).

Stade 4 : plusieurs régions upload (avancé)

Signes : upload US/EU/APAC ; clés ASC et IP par région ; promotion et conformité en ligne dédiée.

Conclusion : plateforme de distribution, pas « un Mac CI de plus » — registry, politique, audit ; hors de ce runbook.

Stade → action (boucle décision)
Stade Action prioritaire
Stage 1Garder un Mac ; optimiser créneaux build/upload
Stage 2Stopper les achats Mac ; modèle A + checklist
Stage 3Étendre le build ; monitoring upload
Stage 4Projet séparé : multi-région, pas patch Fastlane
Déclencheur d’upgrade (problème déjà là)
Si votre CI montre déjà « TestFlight vide par moments + plusieurs Mac + match sur plusieurs nœuds », vous êtes en obligation de role split, pas en phase « acheter un runner ». Bloqués au stade 2 : arbre + anti-modèle B — pas de troisième Mac avant le split.

Verdict final (ce bloc suffit pour exécuter)

Si les trois conditions ci-dessous sont vraies, tranchez ici sans relire l’article :

  • Au moins 2 Mac runners (ou CI multi-nœuds équivalent)
  • Chaîne Fastlane avec TestFlight instable (match failed, processing bloqué, builds absents)
  • match a tourné sur plus d’une machine

👉 N’achetez plus de machines.

👉 Trois actions (démarrables aujourd’hui) :

  1. Arrêter match / sync_code_signing hors nœud upload
  2. Forcer entre DC uniquement .ipa + manifest.json (interdire rsync .xcarchive)
  3. Unifier RUN_ID + GIT_SHA + ipa_sha256 avant upload

Sinon : vous êtes au stade 2 (modèle B). Plus de hardware agrandit la panne. Fastfile et labels workflow d’abord, checklist verte, puis capacité build.

Fastfile upload (modèle A · extrait)
lane :upload_only do |options|
  verify_run_id!(options) # manifest.json
  match(type: "appstore", readonly: true)
  upload_to_testflight(ipa: options[:ipa_path], api_key_path: "asc_api_key.json")
end
Discipline de changement
Semaine du split : pas de rotate match. Rotation certificats = événement séparé : arrêter les deux lanes, rotate uniquement sur upload.

Questions courtes

Le build peut-il archiver sans Distribution ? Selon le projet ; nous exportons une IPA pour signature App Store finale sur l’upload (ou build = compile check, upload resign). Règle : match sur un seul host.

match expire bientôt ? Rotate uniquement sur upload en fenêtre non-readonly ; pause build jusqu’à profils stables.

Différence avec le runbook voyage ? Voyage = Wi‑Fi sur site ; ici = rôles datacenter et frontières Fastlane — checklist copiable telle quelle.

Série : ① Runbook : dual cloud Mac + Fastlane (TestFlight vide / match failed / CI iOS multi-Mac). Suite : ② Build·Sign·Distribute, ③ anti-modèle B ; entrée setup TestFlight.

Pour aller plus loin

Rôles et nœuds : Hong Kong et tarifs. Besoin d'un Mac upload dédié : voir l'article TestFlight.

Hashvps

Bloqué à l'étape 2 ? Role split d'abord

IPv4 fixe sur le nœud upload (liste ASC) ; scale build en APAC.

Voir les offres
Offre limitée