L’archivage fonctionne en local, mais échoue à l’étape de signature sur un Mac dans le cloud avec le message resource fork, Finder information, or similar detritus not allowed. Ce type d’erreur ne vient généralement pas d’un certificat ou d’un profil de provisionnement expiré, mais d’une image, d’un artefact de script ou d’un répertoire copié qui contient des attributs étendus macOS. Ces métadonnées sont intégrées au bundle de l’App lors de la copie des ressources et ne sont détectées qu’au moment où l’outil de signature effectue ses contrôles stricts.
Identifier d’abord la couche où survient l’échec
Ne recréez pas immédiatement les certificats dès que vous voyez un « échec de signature ». Commencez par repérer la première erreur codesign dans le journal de compilation complet, puis notez si l’objet concerné est l’App principale, un Framework, une extension ou un bundle de ressources. Si le journal mentionne explicitement FinderInfo, ResourceFork ou detritus, concentrez l’analyse sur les métadonnées des fichiers.
Les attributs étendus se rencontrent souvent dans les emplacements suivants :
- images, polices ou archives copiées dans le dépôt depuis un gestionnaire de fichiers graphique ;
- ressources extraites d’un répertoire partagé, puis validées directement dans le dépôt ;
- répertoires prégénérés déplacés par un script de build avec
cp -R; - artefacts locaux non suivis par le contrôle de version, mais conservés depuis longtemps dans le répertoire de travail ;
- dépendances restaurées depuis un cache avec leurs métadonnées de fichiers.
La suppression de DerivedData n’efface que les sorties de compilation. Si la contamination se trouve dans les sources ou dans une entrée externe, elle réapparaîtra systématiquement au build suivant.
Conservez d’abord la commande ayant échoué, le chemin de la cible et les journaux, puis procédez au nettoyage. Sinon, même si le build se remet à fonctionner par hasard, vous ne pourrez pas identifier la véritable source de la contamination.
Établir une base de référence en lecture seule
Examiner les entrées du dépôt
xattr -lr répertorie récursivement les chemins et leurs attributs. Commencez par enregistrer les résultats dans un journal sans supprimer les attributs pendant l’analyse :
set -euo pipefail
ROOT="${SRCROOT:-$PWD}"
REPORT="${TMPDIR:-/tmp}/ios-xattr-source.log"
xattr -lr "$ROOT" > "$REPORT" 2>&1 || true
grep -E \
'com\.apple\.(FinderInfo|ResourceFork)' \
"$REPORT" || true
Si le dépôt est volumineux, vous pouvez exclure .git, DerivedData et les caches de dépendances, puis examiner séparément les répertoires réellement inclus dans le bundle. Le nombre de correspondances importe moins que les réponses à trois questions : à quel fichier l’attribut est-il attaché, quel processus a généré ce fichier et par quelle Build Phase entre-t-il dans le bundle ?
| Emplacement détecté | Vérification prioritaire | Principe de traitement |
|---|---|---|
| Assets ou répertoire de ressources | Méthode d’importation, outil de décompression | Corriger le fichier source |
| Répertoire de sortie d’un script | Paramètres de cp et ditto |
Recréer le répertoire temporaire |
| DerivedData | Restauration du cache, anciens artefacts | Vider le cache et reproduire |
| Intérieur d’un Framework | Étapes de téléchargement et d’extraction | Télécharger de nouveau et contrôler |
Examiner le bundle archivé
Si l’archive a déjà été générée, analysez directement le fichier .app pour confirmer que la contamination a atteint le livrable :
ARCHIVE_PATH="$PWD/build/App.xcarchive"
APP_PATH="$ARCHIVE_PATH/Products/Applications/App.app"
REPORT="$PWD/build/xattr-app.log"
test -d "$APP_PATH"
xattr -lr "$APP_PATH" > "$REPORT" 2>&1 || true
if grep -Eq 'com\.apple\.(FinderInfo|ResourceFork)' "$REPORT"; then
echo "forbidden extended attributes found"
exit 1
fi
Cet exemple utilise un chemin fixe. Dans un pipeline réel, il faut identifier l’unique fichier .app à partir du répertoire d’archive et arrêter immédiatement l’exécution si aucun candidat ou plusieurs candidats sont trouvés, afin de ne pas contrôler le mauvais bundle.
Nettoyer sans perdre la traçabilité
Il est déconseillé d’exécuter immédiatement xattr -cr sur l’ensemble de l’espace de travail. Cette commande supprime tous les attributs étendus, élargit inutilement la portée des modifications et peut masquer un problème dans les étapes de téléchargement, d’extraction ou de restauration du cache. Une méthode plus sûre consiste à supprimer uniquement les deux types d’attributs dont l’impact sur la signature a été confirmé :
TARGET="$PWD/StagingPayload"
find "$TARGET" -print0 |
while IFS= read -r -d '' item; do
xattr -d com.apple.FinderInfo "$item" 2>/dev/null || true
xattr -d com.apple.ResourceFork "$item" 2>/dev/null || true
done
Dans l’idéal, TARGET doit désigner une copie temporaire à usage unique plutôt que l’espace de travail d’origine du développeur. Une fois le nettoyage terminé, relancez l’analyse. Si des correspondances subsistent, interrompez le build et n’ajoutez pas || true à la condition de validation finale.
Si les attributs proviennent d’une archive compressée, corrigez l’étape de contrôle qui suit son extraction. S’ils viennent d’un script de build, faites en sorte que le script crée à chaque exécution un répertoire temporaire vide, puis copie une liste explicite de fichiers. Ajouter simplement une commande de nettoyage récursif à la fin laisse la contamination en place et lui permet de réapparaître dans d’autres tâches.
Intégrer les contrôles au processus d’archivage
Contrôler les entrées avant le build
Le contrôle préalable au build doit analyser uniquement les répertoires de ressources qui seront intégrés à l’App, sans parcourir tout le répertoire personnel. En cas de correspondance, affichez le chemin relatif et le nom de l’attribut, puis quittez avec un code différent de zéro. Le pipeline échouera ainsi avant le lancement d’un archivage coûteux, tout en facilitant l’identification de la modification récente en cause.
Le script de contrôle doit être placé sous gestion de versions et exécuté dans un environnement déterministe :
- déterminer la racine du dépôt à partir de l’emplacement du script lui-même ;
- utiliser des séparateurs nuls pour les chemins contenant des espaces ;
- écrire le rapport dans un répertoire d’artefacts propre à la tâche en cours ;
- ne modifier aucun fichier pendant l’analyse ;
- signaler immédiatement toute absence d’un répertoire cible.
Valider la signature après l’archivage
Une fois l’analyse des attributs étendus réussie, utilisez l’outil de signature du système pour vérifier l’archive :
APP_PATH="$PWD/build/App.xcarchive/Products/Applications/App.app"
codesign --verify \
--strict \
--verbose=2 \
"$APP_PATH"
Si l’App contient des Frameworks ou des extensions indépendants, parcourez également ces objets de code imbriqués afin de les vérifier séparément. Ne supposez pas que les composants internes sont valides après avoir contrôlé uniquement le bundle principal. Conservez ensemble les journaux de validation, le chemin de l’archive et l’identifiant du commit source afin de distinguer les cas où les sources sont identiques, mais les entrées restaurées depuis le cache diffèrent.
Terminer le diagnostic avec une liste de validation
Une correction fiable doit remplir simultanément les conditions suivantes :
- les résultats d’analyse des sources et des entrées externes ont été archivés ;
- le processus ayant généré ou copié le fichier contaminé a été identifié ;
- le nettoyage a ciblé uniquement les attributs concernés ou une copie temporaire à usage unique ;
- une nouvelle archive peut être produite après suppression de DerivedData et des caches associés ;
- le bundle final de l’App ne contient ni FinderInfo ni ResourceFork ;
- l’App principale et les objets de code imbriqués passent tous une vérification stricte de la signature ;
- le même commit réussit de manière reproductible dans un nouveau répertoire de travail.
Les problèmes d’attributs étendus sont difficiles à diagnostiquer non pas parce que les commandes sont complexes, mais parce qu’ils traversent quatre couches : le code source, les métadonnées du système de fichiers, le cache et la signature. En transformant la séquence « enregistrer, localiser, nettoyer, valider » en contrôles obligatoires, ces incidents ne nécessitent plus de se connecter manuellement à un nœud pour effectuer une correction ponctuelle, et les indices ne disparaissent plus lors d’un changement de répertoire de travail.
Questions fréquentes
Pourquoi supprimer DerivedData ne corrige-t-il pas toujours l’erreur ?
Si FinderInfo ou ResourceFork est présent dans les sources, un dossier copié par script ou un fichier téléchargé, chaque reconstruction le réintroduit. Il faut analyser les entrées avant de recréer DerivedData.
Faut-il exécuter xattr -cr sur tout le dépôt ?
Non. Commencez par inventorier les fichiers concernés, puis supprimez seulement FinderInfo et ResourceFork. Réservez le nettoyage récursif complet à une copie de travail temporaire.
Comment valider l’archive après le nettoyage ?
Analysez le bundle App pour vérifier l’absence des attributs ciblés, puis lancez codesign --verify --strict. Conservez également les journaux et la somme de contrôle de l’archive.
Lancez votre prochaine tâche sur un nœud physique dédié
Utilisez un Mac dans le cloud équipé d’une puce M4, de 16 Go de RAM et d’un SSD de 256 Go, avec un nœud à Singapour, Tokyo, Séoul ou Hong Kong selon la durée de votre tâche.