Lorsqu’un projet iOS déplace ses niveaux, ses textures haute définition ou ses modèles hors ligne vers les On-Demand Resources, la taille du paquet d’installation diminue généralement de manière sensible. Pour autant, une compilation réussie ne garantit pas que les ressources soient utilisables. Les incidents les plus fréquents ne sont pas des erreurs de compilation, mais des balises manquantes, l’intégration involontaire de toutes les ressources dans un paquet de test, ou une divergence entre les packs de ressources du livrable et les requêtes effectuées par le code. Un Mac cloud permet de systématiser ces contrôles sous la forme d’une tâche indépendante : archiver chaque fois depuis un espace de travail propre, conserver les manifestes et les sommes de contrôle, puis exécuter une véritable requête.
Définir d’abord un périmètre de validation mesurable
La validation des ODR doit couvrir au minimum trois niveaux : la configuration du projet, les livrables exportés et les requêtes à l’exécution. N’en examiner qu’un seul laisse nécessairement des angles morts.
Au niveau du projet, il faut vérifier que les On-Demand Resources sont activées pour la Target et que chaque balise du catalogue de ressources a une fonction clairement définie. Au niveau des livrables, le contrôle porte sur les fichiers .assetpack, les manifestes et les empreintes des fichiers. Au niveau de l’exécution, il faut valider la première requête, la libération des ressources et une nouvelle requête.
Le simple fait que « l’application démarre » ne constitue pas un critère suffisant pour valider les ODR. Même l’absence totale des ressources d’un niveau jamais consulté n’empêchera pas nécessairement l’écran d’accueil de s’ouvrir.
Pour chaque balise, il est recommandé de consigner quatre informations : le responsable, l’écran déclencheur, le type de ressource attendu et le caractère obligatoire ou non de la ressource lors de l’installation initiale. Ces données doivent figurer dans un manifeste en texte brut conservé dans le dépôt, et non uniquement dans l’interface de Xcode.
Maîtriser la granularité des packs avec des balises stables
Les balises ne doivent pas correspondre directement, une à une, au nombre de dossiers. Une granularité trop fine produit une multitude de petits packs et des requêtes fréquentes ; une granularité trop large oblige l’utilisateur à télécharger tout un ensemble de ressources sans rapport avec la page consultée. Une méthode plus robuste consiste à découper les ressources selon le parcours utilisateur, avec par exemple level-01, tutorial-audio ou model-basic, tout en veillant à ce que les noms demandés dans le code correspondent exactement aux balises du catalogue de ressources.
Soumettre le manifeste des balises à un contrôle bloquant
Le dépôt peut contenir la liste des balises autorisées :
level-01
level-02
tutorial-audio
model-basic
Le script de build extrait les balises depuis le fichier de projet ou les informations générées sur les ressources, les trie, puis les compare à cette liste. Toute nouvelle balise doit s’accompagner d’une modification du manifeste. Lorsqu’une balise est supprimée, il faut également vérifier les appels à NSBundleResourceRequest dans le code. Les fautes de frappe sont ainsi détectées dès l’étape de fusion, plutôt qu’à l’exécution.
Les noms de balises doivent uniquement utiliser des caractères ASCII stables, sans espaces, sans mélange de majuscules et de minuscules, ni numéros de version temporaires. Les mises à jour de ressources doivent être représentées par une version de contenu ou une somme de contrôle, et non par une succession de noms impossibles à maintenir tels que level-final-v2-new.
Fixer les conditions d’archivage et d’exportation
Pour un même commit, il faut conserver un workspace, un scheme, une configuration Release et des options d’exportation identiques. Une tâche exécutée sur un nœud VMArm peut commencer par vider le répertoire de sortie de l’exécution en cours, mais elle ne doit pas supprimer indistinctement les caches globaux. Il deviendrait alors difficile de déterminer si les différences proviennent des ressources ou de l’environnement.
set -euo pipefail
: "${WORKSPACE:?WORKSPACE is required}"
: "${SCHEME:?SCHEME is required}"
ROOT="$PWD"
ARCHIVE_PATH="$ROOT/out/Game.xcarchive"
EXPORT_DIR="$ROOT/out/export"
rm -rf "$ARCHIVE_PATH" "$EXPORT_DIR"
mkdir -p "$EXPORT_DIR"
xcodebuild \
-workspace "$WORKSPACE" \
-scheme "$SCHEME" \
-configuration Release \
-destination 'generic/platform=iOS' \
-archivePath "$ARCHIVE_PATH" \
clean archive
xcodebuild \
-exportArchive \
-archivePath "$ARCHIVE_PATH" \
-exportPath "$EXPORT_DIR" \
-exportOptionsPlist "$ROOT/ci/ExportOptions.plist"
Pour le circuit de validation locale, embedOnDemandResourcesAssetPacksInBundle peut être défini sur true afin de confirmer d’abord que le contenu des packs et la logique des requêtes sont corrects. Le circuit de production doit utiliser une configuration d’exportation adaptée au mode de distribution réel, sans reprendre le réglage d’intégration locale. Les livrables des deux circuits doivent être enregistrés dans des répertoires distincts afin d’éviter qu’un paquet de test n’écrase celui destiné à la publication.
Contrôler les livrables sur trois niveaux
Le premier niveau vérifie que les fichiers existent. Le deuxième s’assure que les fichiers plist peuvent être analysés. Le troisième génère une somme de contrôle stable pour tous les fichiers de ressources, afin de comparer deux builds issus du même commit.
set -euo pipefail
ARCHIVE_PATH="$PWD/out/Game.xcarchive"
EXPORT_DIR="$PWD/out/export"
REPORT_DIR="$PWD/out/report"
mkdir -p "$REPORT_DIR"
find "$ARCHIVE_PATH" "$EXPORT_DIR" \
-name '*.assetpack' \
-print | LC_ALL=C sort > "$REPORT_DIR/assetpacks.txt"
find "$ARCHIVE_PATH" "$EXPORT_DIR" \
-name 'AssetPackManifest.plist' \
-exec plutil -lint {} \; > "$REPORT_DIR/plist-lint.txt"
find "$ARCHIVE_PATH" "$EXPORT_DIR" \
-type f \
\( -name '*.car' -o -name '*.plist' -o -name '*.assetpack' \) \
-exec shasum -a 256 {} \; |
LC_ALL=C sort > "$REPORT_DIR/checksums.txt"
test -s "$REPORT_DIR/assetpacks.txt"
Si un .assetpack est en réalité un répertoire, la dernière commande de calcul d’empreinte ne traitera pas directement son contenu. Il faut donc inclure dans le contrôle les fichiers ordinaires contenus dans ce répertoire. Le rapport doit mentionner l’identifiant du commit, la version de Xcode, le scheme et l’empreinte du fichier de configuration d’exportation, sans y inscrire de clé privée de signature, de jeton ni de chemin complet vers des identifiants.
Lors de la comparaison de deux rapports, il faut d’abord distinguer un simple « changement d’ordre des fichiers » d’une « modification du contenu ». Un tri uniforme élimine le premier cas. Si les empreintes d’un même commit continuent malgré tout à varier, il convient de vérifier si les scripts de génération inscrivent un horodatage, le chemin absolu de l’espace de travail ou un identifiant aléatoire.
Valider l’exécution et diagnostiquer les incidents
Les tests d’exécution doivent commencer depuis un état propre. Après avoir installé le paquet de validation, demandez une balise qui ne fait pas partie de l’installation initiale et consignez trois événements : le début de la requête, l’autorisation d’accéder à la ressource et sa libération. Fermez ensuite l’application, nettoyez l’environnement de test, puis répétez l’opération afin de confirmer que la réussite ne dépendait pas d’un ancien cache.
Ordre de diagnostic des symptômes courants
Si la requête échoue immédiatement, commencez par comparer la balise utilisée dans le code à celle du catalogue de ressources. Si elle reste longtemps en attente, vérifiez que le pack de ressources a été correctement exporté ainsi que l’état du réseau de test. Si l’intégration locale fonctionne mais que le circuit de production échoue, comparez en priorité les deux configurations ExportOptions et les paramètres d’hébergement des ressources. Si seules certaines ressources manquent, vérifiez si des fichiers portant le même nom ont été affectés à plusieurs balises ou si les ressources concernées appartiennent encore au paquet principal.
Une répétition sans limite ne doit pas servir à masquer les erreurs. Définissez un délai d’expiration explicite pour chaque requête. En cas d’échec, les journaux ne doivent contenir que la balise, le domaine d’erreur, le code d’erreur et l’étape concernée, jamais de jeton d’accès ni de chemin sensible. Une fois la validation terminée, conservez les rapports, l’empreinte de la configuration d’exportation et les journaux d’échec, puis supprimez les paquets temporaires et les caches de test. Lors de la prochaine modification des ODR, toute divergence pourra ainsi être analysée en comparant directement les livrables, plutôt qu’en essayant de deviner à nouveau ce que Xcode a produit.
Questions fréquentes
Faut-il intégrer les packs ODR dans une version de développement ?
Oui pour une première voie de validation locale. Activez embedOnDemandResourcesAssetPacksInBundle afin d’isoler les erreurs de paquetage, puis réalisez un second export avec les paramètres réels de distribution.
La taille du fichier IPA suffit-elle pour valider ODR ?
Non. Il faut aussi contrôler le nombre de packs, l’association des balises, les fichiers AssetPackManifest.plist, les sommes de contrôle et une nouvelle requête après suppression du cache local.
Choisissez un Mac dans le cloud toujours disponible pour votre prochaine compilation Xcode
Vérifiez la puce, la mémoire, le stockage, la période de facturation et la région du nœud, puis lancez la configuration. La disponibilité réelle est indiquée en temps réel par la console.