Gardez votre pipeline, changez de machine

Ces pipelines tournent déjà sur un Mac dans le cloud

Déplacez les étapes de build et de test qui nécessitent macOS vers un Mac mini physique dédié. Les projets iOS natifs, Flutter, Unity et MLX ont chacun leurs propres limites de ressources : commencez par vérifier les commandes et prérequis, puis choisissez une configuration selon la mémoire, le cache et le parallélisme. Des workflows prêts à l’emploi, pas des benchmarks.

Machine physique dédiée, pas une machine virtuelle. Location à la journée à partir de $20.5/jour ; la disponibilité affichée dans la console fait foi.

Choisir selon la charge de travail

5 cas d’usage au total, tous affichés. Choisissez une catégorie pour mettre en évidence les cas correspondants et y accéder, sans masquer les autres.

Du déclencheur aux artefacts validés

Trouvez l’étape à exécuter.

Exécutez les commandes suivantes sur le nœud. Installez d’abord les dépendances du projet, puis définissez les variables d’environnement correspondantes. Les chemins doivent pointer vers votre projet et vos fichiers de configuration. Le bouton Copier copie uniquement la commande, sans lancer de tâche.

iOS natif · build nocturne

Déclenchez l’archive à chaque push Git et confiez l’envoi à fastlane.

Enregistrez le Mac dans le cloud comme runner auto-hébergé GitHub Actions, GitLab Runner ou agent Jenkins. Après un push sur la branche de release, récupérez un commit précis, puis générez l’archive Release et l’IPA. L’envoi vers TestFlight est une étape distincte : vous pouvez ainsi relancer séparément un build ou un envoi en échec.

Préparez ces trois éléments

  • Définissez WORKSPACE, SCHEME et EXPORT_OPTIONS pour indiquer respectivement le workspace, le scheme partagé et la configuration d’export.
  • Configurez le certificat de signature et le profil de provisionnement pour l’utilisateur qui lance le build. Vous pouvez les gérer avec fastlane match et injecter les identifiants déchiffrés via les secrets de la CI.
  • Définissez ASC_API_KEY_JSON pour indiquer le fichier JSON de la clé API App Store Connect utilisée par fastlane. Ne stockez pas cette clé dans votre dépôt de code.

Que vérifier à la validation

L’archive build/App.xcarchive, l’IPA exporté, l’identifiant du commit et la version de Xcode. Vérifiez que TestFlight a bien reçu la version correspondante : une commande de build terminée avec succès ne garantit pas la fin de l’envoi.

Pourquoi ce modèle : les 24 Go de mémoire unifiée du Host M4 Plus conviennent aux builds quotidiens avec plusieurs targets. Commencez par les exécuter en série, puis augmentez le parallélisme en fonction de la pression mémoire et de l’espace occupé par DerivedData.

archive → export → envoi
set -euo pipefail
: "${WORKSPACE:?Set WORKSPACE}"
: "${SCHEME:?Set SCHEME}"
: "${EXPORT_OPTIONS:?Set EXPORT_OPTIONS}"
: "${ASC_API_KEY_JSON:?Set ASC_API_KEY_JSON}"

mkdir -p build
xcodebuild -version
xcodebuild \
  -workspace "$WORKSPACE" -scheme "$SCHEME" \
  -configuration Release \
  -destination 'generic/platform=iOS' \
  -archivePath build/App.xcarchive archive

xcodebuild -exportArchive \
  -archivePath build/App.xcarchive \
  -exportPath build/export \
  -exportOptionsPlist "$EXPORT_OPTIONS"

IPA_PATH="$(find build/export -type f -name '*.ipa' -print -quit)"
test -n "$IPA_PATH"
bundle exec fastlane pilot upload \
  --ipa "$IPA_PATH" \
  --api_key_path "$ASC_API_KEY_JSON"
Configuration utilisée : Host M4 Plus · M4 / 24 Go / 512 Go Nœud conseillé : Japon (Tokyo)
Louer le Host M4 Plus

Multiplateforme · Flutter

Gardez Android sur Linux et migrez uniquement l’étape iOS.

Inutile de déplacer tout le pipeline multiplateforme. Le runner Linux conserve les tâches Android ; le Mac dans le cloud se charge de CocoaPods, de la compilation Xcode et de l’export IPA. Utilisez le même identifiant de commit sur les deux environnements et regroupez les artefacts à la fin. En cas d’échec, relancez uniquement la tâche concernée.

Définissez les conditions d’invalidation du cache

  • Verrouillez les versions de Flutter, Ruby, CocoaPods et Xcode, et conservez pubspec.lock, Podfile.lock et Gemfile.lock.
  • Mettez en cache les téléchargements Pub et CocoaPods. La clé de cache doit inclure au minimum les versions de la chaîne d’outils et l’empreinte des fichiers de verrouillage des dépendances.
  • Évitez que plusieurs tâches concurrentes écrivent dans le même répertoire de projet. Isolez DerivedData et les répertoires de sortie par tâche pour empêcher la contamination des caches.

Que vérifier à la validation

Conservez les IPA signés de build/ios/ipa , les journaux de build et les fichiers de verrouillage des dépendances. Vérifiez les artefacts en les installant sur un appareil ou en lançant une tâche de test ultérieure, puis marquez le build comme prêt à être publié.

Pourquoi ce modèle : le Host M4 Lite est un bon point de départ pour une seule tâche. Si vous ouvrez aussi un simulateur, lancez des tests et empaquetez l’application, mesurez d’abord le pic de mémoire avant d’envisager le Host M4 Plus, plutôt que d’augmenter directement le parallélisme.

Flutter · tâche iOS
set -euo pipefail
: "${EXPORT_OPTIONS:?Set EXPORT_OPTIONS}"

flutter --version
xcodebuild -version
flutter doctor -v
bundle check || bundle install
flutter pub get

(
  cd ios
  bundle exec pod install --deployment
)

flutter build ipa \
  --release \
  --export-options-plist="$EXPORT_OPTIONS"

find build/ios/ipa -type f -name '*.ipa' -print
Configuration utilisée : Host M4 Lite · M4 / 16 Go / 256 Go Nœud conseillé : Singapour
Louer le Host M4 Lite

Jeu vidéo · build iOS

Récupérez le projet exporté par Unity, puis signez-le, générez le paquet et vérifiez sa taille.

Le traitement des ressources Unity et la compilation Xcode sont deux étapes distinctes. Utilisez d’abord le processus d’export de votre projet pour générer le projet Xcode, puis lancez l’archive et l’export sur le Mac dans le cloud. Comparez la taille du paquet avec les mêmes paramètres de ressources afin d’identifier si les écarts viennent des ressources, des options de compilation ou de la méthode d’export.

Définissez clairement la limite d’export

  • UNITY_IOS_DIR doit pointer vers le répertoire du projet iOS déjà exporté. La commande ci-dessous démarre à l’étape Xcode et ne remplace pas le script de build Unity de votre projet.
  • Si un plugin a généré un workspace, définissez UNITY_WORKSPACE ; sinon, utilisez Unity-iPhone.xcodeproj. Ne mélangez pas ces deux points d’entrée.
  • Préparez la signature et EXPORT_OPTIONS. Pour obtenir un rapport App Thinning, activez l’option correspondante dans la configuration d’export.

Que vérifier à la validation

Vérifiez la taille du fichier IPA, les journaux d’export et les changements apportés aux ressources. La taille compressée de l’IPA ne correspond pas nécessairement à la taille téléchargée ou installée par l’utilisateur. Pour décider de la publication, tenez aussi compte du rapport d’export et du traitement de distribution.

Pourquoi ce modèle : avec 64 Go de mémoire unifiée et un SSD de 2 To, le Host M4 Pro convient aux projets riches en ressources et aux caches d’archives volumineux. Mesurez d’abord la consommation à chaque étape — import des ressources, compilation et export — puis planifiez la file de tâches.

export Unity → Xcode
set -euo pipefail
: "${UNITY_IOS_DIR:?Set UNITY_IOS_DIR}"
: "${EXPORT_OPTIONS:?Set EXPORT_OPTIONS}"

mkdir -p build
if [ -n "${UNITY_WORKSPACE:-}" ]; then
  xcodebuild -workspace "$UNITY_WORKSPACE" \
    -scheme Unity-iPhone -configuration Release \
    -destination 'generic/platform=iOS' \
    -archivePath build/Game.xcarchive archive
else
  xcodebuild \
    -project "$UNITY_IOS_DIR/Unity-iPhone.xcodeproj" \
    -scheme Unity-iPhone -configuration Release \
    -destination 'generic/platform=iOS' \
    -archivePath build/Game.xcarchive archive
fi

xcodebuild -exportArchive \
  -archivePath build/Game.xcarchive \
  -exportPath build/game-export \
  -exportOptionsPlist "$EXPORT_OPTIONS"

find build/game-export -type f -name '*.ipa' \
  -exec du -h {} \;
Configuration utilisée : Host M4 Pro · M4 Pro / 64 Go / 2 To Nœud conseillé : Corée du Sud (Séoul)
Louer le Host M4 Pro

iOS natif · tests de compatibilité

Verrouillez Xcode, puis exécutez la matrice de simulateurs étape par étape.

Vérifier la compatibilité avec un nouveau système ne se résume pas à réussir la compilation. Ajoutez aux tests la navigation principale, les demandes d’autorisation, le mode sombre et les mises en page essentielles. Conservez les résultats par version de Xcode et runtime de simulateur. Commencez par une matrice reproductible exécutée en série, puis déterminez quels tests méritent d’être parallélisés.

Assurez le suivi des versions et des appareils

  • Gérez plusieurs versions de Xcode avec xcodes. Sélectionnez la version pour chaque tâche via DEVELOPER_DIR afin d’éviter que des tâches concurrentes ne modifient la chaîne d’outils par défaut de toute la machine.
  • Commencez par consulter les simulateurs disponibles dans la version actuelle de Xcode, puis attribuez des UDID différents à SIM_A et à SIM_B . Leurs runtimes doivent être installés au préalable.
  • Conservez les résultats .xcresult, et pas seulement la dernière ligne du terminal. Les captures d’écran de l’interface, les tests en échec et les relances doivent tous être associés au même commit.

Que vérifier à la validation

Vérifiez le code de sortie des tests et le bundle de résultats pour chaque cible. Les tests sur simulateur ne remplacent pas les vérifications sur appareil réel concernant les périphériques, les performances et la distribution ; planifiez-les séparément.

Pourquoi ce modèle : le Host M4 Plus constitue un bon point de départ pour les tests de régression quotidiens. Le nombre de simulateurs dépend de la pression mémoire réelle : 24 Go ne permettent pas un parallélisme illimité.

Xcode · matrice de simulateurs
set -euo pipefail
: "${DEVELOPER_DIR:?Set DEVELOPER_DIR}"
: "${WORKSPACE:?Set WORKSPACE}"
: "${SCHEME:?Set SCHEME}"
: "${SIM_A:?Set SIM_A}"
: "${SIM_B:?Set SIM_B}"
export DEVELOPER_DIR

mkdir -p build
xcodebuild -version
xcrun simctl list devices available

RUN_ID="$(date +%s)-$$"
for DEVICE_ID in "$SIM_A" "$SIM_B"; do
  xcodebuild test \
    -workspace "$WORKSPACE" \
    -scheme "$SCHEME" \
    -destination "platform=iOS Simulator,id=$DEVICE_ID" \
    -parallel-testing-enabled NO \
    -resultBundlePath \
      "build/$RUN_ID-$DEVICE_ID.xcresult"
done
Configuration utilisée : Host M4 Plus · M4 / 24 Go / 512 Go Nœud conseillé : Hong Kong
Louer le Host M4 Plus

IA · expérimentations d’inférence MLX

Chargez le modèle dans la mémoire unifiée et vérifiez d’abord qu’il s’exécute de façon stable.

Sur un nœud physique Apple Silicon, chargez avec MLX un modèle compatible et relevez la vitesse de génération, le pic de mémoire et la longueur du contexte. Commencez par vérifier une requête seule, puis testez le traitement par lots. Les builds et les expériences d’inférence partagent les ressources de la machine : ne les faites pas tourner à pleine charge simultanément sans mesures préalables.

Vérifiez d’abord le modèle et les ressources nécessaires

  • MODEL_DIR doit pointer vers le répertoire d’un modèle MLX compatible déjà préparé. Vérifiez sa provenance, sa licence d’utilisation, son format de quantification et les versions de ses dépendances.
  • Les 64 Go correspondent à la mémoire unifiée de toute la machine : le système, les poids du modèle, le cache et les autres processus en consomment une partie. La possibilité de charger un modèle dépend de sa configuration et de la longueur du contexte.
  • Utilisez des prompts et des longueurs de génération fixes, et mesurez le démarrage à froid ainsi que les requêtes suivantes. N’incluez pas le téléchargement du modèle dans le débit d’inférence.

Que vérifier à la validation

Conservez la version du modèle, la configuration de quantification, l’environnement MLX et les journaux d’exécution. Utilisez /usr/bin/time -l pour suivre la consommation du processus, puis vérifiez la pression mémoire du système afin de détecter une éventuelle pagination.

Pourquoi ce modèle : les 64 Go de mémoire unifiée du Host M4 Pro conviennent aux expériences qui nécessitent davantage de mémoire. Le SSD de 2 To stocke les fichiers du modèle et les artefacts d’expérience, mais n’augmente pas la mémoire disponible pour le modèle.

MLX · inférence locale
set -euo pipefail
: "${MODEL_DIR:?Set MODEL_DIR}"

python3 -m venv .venv
. .venv/bin/activate
python -m pip install mlx-lm
mkdir -p build

python -m pip freeze > build/mlx-environment.txt
/usr/bin/time -l \
  python -m mlx_lm.generate \
    --model "$MODEL_DIR" \
    --prompt "Explain reproducible builds." \
    --max-tokens 128 \
    > build/mlx-output.txt \
    2> build/mlx-metrics.txt

cat build/mlx-output.txt
cat build/mlx-metrics.txt
Configuration utilisée : Host M4 Pro · M4 Pro / 64 Go / 2 To Nœud conseillé : côte ouest des États-Unis
Louer le Host M4 Pro

Après avoir copié une commande, vérifiez les variables et les paramètres de signature dans le répertoire de votre projet avant de l’exécuter.

Une recommandation n’est pas une garantie de performance

Ajustez la configuration à partir d’une tâche complète.

Les nœuds proposés ci-dessus tiennent compte des fuseaux horaires de collaboration des équipes ; ils ne reflètent pas des mesures de latence réseau. L’emplacement du dépôt de code, du stockage des artefacts et des personnes qui utilisent la machine compte également.

01

Mesurez les pics de ressources

Avec un commit et des versions de dépendances fixes, exécutez une tâche complète. Relevez la pression mémoire, la taille du cache et celle des artefacts. Ne choisissez pas une configuration sur la seule base du temps d’une compilation.

02

Distinguez la mise en file d’attente de l’exécution

Commencez avec un seul exécuteur. Une fois la tâche stabilisée, augmentez le parallélisme. Mesurez séparément le temps d’attente du runner, celui du téléchargement des dépendances et celui de la compilation.

03

Choisissez un nœud proche des équipes

Cinq nœuds sont disponibles : Singapour, Japon (Tokyo), Corée du Sud (Séoul), Hong Kong et côte ouest des États-Unis. Vérifiez d’abord la synchronisation du projet et la connexion interactive, puis définissez un emplacement d’exécution commun à l’équipe.

Définissez clairement les critères de validation

Que voulez-vous retrouver demain matin ?

Voici des objectifs d’utilisation par rôle, et non des témoignages clients ni des résultats de tests. Intégrer ces objectifs aux critères de validation du pipeline est plus utile que de chercher à accélérer une seule compilation.

« Je veux retrouver le matin l’archive, les résultats des tests et les journaux d’échec correspondant au commit, sans avoir à vérifier d’abord la machine de build du bureau. »
Responsable iOS · objectif de build nocturne
« Je migre uniquement l’étape iOS de Flutter. Les deux plateformes utilisent le même commit et, en cas d’échec, je peux relancer chaque tâche séparément sans devoir reconstruire tout le pipeline. »
Architecte mobile · objectif de séparation du pipeline
« Je veux conserver ensemble la version du modèle, la consommation mémoire et les résultats générés. L’expérience doit être reproductible pour que je puisse choisir la bonne machine la prochaine fois. »
Ingénieur en apprentissage automatique · objectif d’expérimentation d’inférence

Choisissez l’étape à exécuter, puis la machine.

Pour démarrer avec une seule tâche, choisissez le Host M4 Lite ; pour plusieurs targets et les tests de régression quotidiens, le Host M4 Plus ; pour les grands projets et les expériences gourmandes en mémoire, le Host M4 Pro. Consultez la page des offres pour comparer les trois configurations, les quatre durées de location et les options supplémentaires, puis passez commande.

Tous les paiements sont en dollars américains. Seuls USDT-TRC20 et Visa / Mastercard / Amex (via Stripe) sont acceptés ; les moyens de paiement réellement disponibles dépendent de la réponse de l’interface backend.