Article technique

Prévalider les catalogues d’assets iOS avec actool sur un Mac cloud

Prévalider les catalogues d’assets iOS avec actool sur un Mac cloud

Un seul emplacement d’icône oublié peut ne se révéler qu’à la toute fin de l’archivage. Dans un pipeline iOS exécuté sur un Mac cloud, les dépendances ont alors déjà été résolues, le code source compilé et les tests lancés, avant que le processus n’échoue à cause d’une erreur de métadonnées dans Assets.xcassets. Une approche plus directe consiste à exécuter séparément actool, l’outil appelé en interne par Xcode, afin d’interrompre le pipeline dès qu’un problème d’asset est détecté.

Définir le périmètre de la prévalidation avec actool

actool lit les catalogues d’assets et compile leurs ressources en fonction de la plateforme, de la cible de déploiement et du type d’appareil. Exécuté séparément, il permet de détecter un fichier Contents.json non valide, un fichier d’image absent d’un emplacement, un attribut non reconnu, un nom en double ou encore une incompatibilité entre AppIcon et la plateforme cible.

Il ne remplace pas une compilation complète. Certaines erreurs peuvent n’apparaître qu’à l’étape xcodebuild : référence dans le code source à un nom de ressource inexistant, catalogues d’assets différents selon les targets ou réglages de compilation remplaçant le nom d’AppIcon. L’ordre recommandé pour le pipeline est le suivant :

Étape Éléments vérifiés Coût d’un échec
Vérification de la syntaxe JSON Possibilité d’analyser Contents.json Minimal
Prévalidation avec actool Structure des ressources et paramètres de plateforme Faible
Compilation Xcode Targets, références du code source et édition de liens Élevé
Tests et archivage Comportement à l’exécution et livrables Maximal

L’objectif de la prévalidation n’est pas de reproduire l’intégralité de Xcode, mais d’intercepter au plus tôt les erreurs d’assets dont le résultat est certain et la correction clairement identifiable.

Figer la chaîne d’outils et les paramètres d’entrée

Commencez par vérifier quelle version de Xcode est réellement utilisée par la tâche. Ne partez pas du principe que le terminal interactif et le processus CI emploient le même répertoire de développement.

xcode-select -p
xcodebuild -version
xcrun --find actool
xcrun actool --version

Si plusieurs versions de Xcode sont installées sur les nœuds, définissez explicitement DEVELOPER_DIR au démarrage de la tâche et consignez la sortie de xcodebuild -version dans le journal de compilation. La plateforme, la version minimale du système, le type d’appareil et le nom d’AppIcon utilisés par le script doivent également correspondre aux réglages de compilation du projet. Dans le cas contraire, une prévalidation réussie indique seulement qu’une autre combinaison de paramètres peut être compilée, et non que la véritable target est valide.

Avant d’exécuter actool, effectuez aussi une vérification légère des fichiers JSON du répertoire :

find App/Assets.xcassets -name Contents.json -print0 |
while IFS= read -r -d '' file; do
  plutil -lint "$file"
done

Cette étape permet de localiser précisément les résidus de conflits de fusion, les caractères superflus en fin de fichier et les fichiers endommagés.

Écrire un script directement exécutable dans la CI

Le script suivant centralise les sorties dans .ci-artifacts/actool et conserve l’intégralité des diagnostics en cas d’échec, afin que la CI puisse les collecter comme pièces jointes. Le répertoire, la cible de déploiement et le nom d’AppIcon doivent être transmis par des paramètres ou par la configuration du projet ; évitez de dupliquer le script pour maintenir plusieurs variantes.

#!/bin/bash
set -euo pipefail

CATALOG="${1:-App/Assets.xcassets}"
DEPLOYMENT_TARGET="${DEPLOYMENT_TARGET:-16.0}"
APP_ICON_NAME="${APP_ICON_NAME:-AppIcon}"
OUT=".ci-artifacts/actool"

rm -rf "$OUT"
mkdir -p "$OUT/compiled"
export LANG=en_US.UTF-8

if ! xcrun actool "$CATALOG" \
  --compile "$OUT/compiled" \
  --platform iphoneos \
  --minimum-deployment-target "$DEPLOYMENT_TARGET" \
  --target-device iphone \
  --app-icon "$APP_ICON_NAME" \
  --output-partial-info-plist "$OUT/partial-info.plist" \
  --notices --warnings --errors \
  >"$OUT/actool.log" 2>&1; then
  cat "$OUT/actool.log"
  exit 1
fi

cat "$OUT/actool.log"
plutil -lint "$OUT/partial-info.plist"

L’option set -euo pipefail empêche le pipeline de continuer après l’échec d’une commande. Le journal est d’abord écrit dans un fichier, puis affiché, afin de préserver à la fois le code de sortie et les diagnostics. En raccordant directement la commande à un pipeline complexe, on risque de récupérer par erreur l’état de la dernière commande seulement.

Gérer les avertissements et les faux positifs courants

Ne pas transformer immédiatement tous les avertissements en erreurs bloquantes

Les anciens projets peuvent avoir accumulé des apparences d’appareil non attribuées, des ensembles d’images inutilisés ou des avertissements de nommage. Lors de la première intégration, conservez les journaux et établissez une référence, puis ne rendez bloquants que les problèmes avérés. Faire échouer la tâche pour chaque ligne contenant warning: conduit généralement l’équipe à désactiver le contrôle plutôt qu’à corriger les ressources.

Il est recommandé de bloquer immédiatement les fichiers JSON non valides, les fichiers de ressources manquants, les emplacements AppIcon obligatoires absents et les noms en double. Pour les ressources inutilisées et les avertissements similaires, commencez par en comptabiliser le nombre, fixez une échéance de nettoyage, puis renforcez progressivement les règles.

Distinguer la plateforme du simulateur de celle des appareils réels

Une prévalidation réussie uniquement avec iphonesimulator ne garantit pas que iphoneos passera également. Les exigences liées aux appareils, les règles applicables aux icônes et la forme des artefacts peuvent produire des diagnostics différents. Si le pipeline compile les deux types de targets, exécutez deux contrôles distincts et utilisez des répertoires de sortie séparés pour éviter que le second résultat n’écrase le premier.

Pour une target incluant l’iPad, ajoutez également le paramètre --target-device ipad correspondant. Ne déclarez pas uniquement iphone dans le but de faire réussir le contrôle : l’ensemble des appareils doit refléter la configuration réelle de la target.

Intégrer le contrôle au pipeline et valider son résultat

Il n’est pas nécessaire d’attendre l’installation des dépendances pour lancer la prévalidation, car actool dépend généralement uniquement de Xcode et des ressources présentes dans le dépôt. Le meilleur emplacement se situe après l’extraction du code et avant la résolution des dépendances. Ainsi, même si le service de gestion des paquets ralentit temporairement, les erreurs d’assets sont signalées rapidement.

Pour la première mise en service, préparez trois cas d’échec : rendez un fichier Contents.json invalide, déplacez temporairement un fichier d’icône référencé et remplacez le nom d’AppIcon par une valeur inexistante. Vérifiez que chaque tâche se termine avec un état non nul, que le journal indique le répertoire précis et que .ci-artifacts/actool est bien conservé par le système. Restaurez ensuite les fichiers, puis confirmez que la prévalidation et la compilation complète réussissent toutes les deux.

Si le dépôt contient plusieurs targets d’application, maintenez une liste associant « target, répertoire de ressources, plateforme et nom d’AppIcon », puis parcourez-la élément par élément, au lieu de transmettre tous les répertoires à une seule commande. Les erreurs pourront ainsi être rattachées directement au module concerné, sans que les paramètres d’une target ne masquent les problèmes d’une autre.

Conservez au final deux niveaux de contrôle : actool détecte rapidement les erreurs déterministes dans les répertoires de ressources, tandis que la compilation Xcode complète valide l’intégration des targets et les livrables finaux. Une fois ces responsabilités clairement séparées, les problèmes d’assets apparaissent plus tôt et les journaux d’échec indiquent plus directement l’emplacement à corriger.

Questions fréquentes

Le contrôle actool remplace-t-il un build Xcode complet ?

Non. Il détecte plus tôt les erreurs du catalogue et des paramètres, mais le build final doit conserver le schéma, le SDK et la configuration de livraison.

Faut-il faire échouer la CI pour chaque avertissement actool ?

Pas immédiatement. Il faut d’abord classer les avertissements existants, puis bloquer les défauts certains comme un JSON invalide ou une icône obligatoire absente.

OwnAMac Mac dans le cloud

Lancez votre prochaine compilation sur un nœud physique Apple Silicon dédié

Choisissez parmi trois niveaux de configuration et cinq nœuds selon la taille de votre tâche. Le calcul et le stockage ne sont pas partagés avec d’autres clients. Tous les nœuds fonctionnent normalement 365 jours par an ; leur disponibilité réelle est indiquée en temps réel par la console.

Choisir une configuration et commander