Nettoyer les métadonnées des artefacts Mac cloud CI

Nettoyer les métadonnées des artefacts Mac cloud CI

Un build exécuté sur un Mac cloud peut réussir et l’archive se décompresser correctement, sans empêcher le destinataire de trouver des fichiers comme ._Config.json ou .DS_Store, voire des attributs étendus d’origine inconnue lors de l’envoi. Le compilateur est rarement en cause. Le problème vient généralement des opérations réalisées dans Finder, des copies entre systèmes de fichiers et des différences de traitement des métadonnées macOS par les outils d’archivage. La solution ne consiste pas à nettoyer brutalement l’espace de travail, mais à décomposer la livraison en quatre étapes auditables : mise en zone temporaire, analyse, archivage et vérification.

Définir ce qui peut entrer dans le livrable

Outre son nom et son contenu, un fichier macOS peut transporter des attributs étendus, des branches de ressources et des métadonnées Finder. Ces éléments ne posent pas nécessairement problème sur le système de fichiers local, mais peuvent devenir des fichiers annexes AppleDouble une fois placés dans une archive ZIP, un volume partagé ou un stockage objet.

Définissez les règles applicables aux artefacts avant de créer l’archive, plutôt que de supprimer des fichiers au fil de l’opération :

Objet Politique par défaut Motif
.DS_Store Refuser Décrit uniquement l’affichage du dossier dans Finder
._* Refuser Souvent généré lors du transfert de branches de ressources entre systèmes de fichiers
com.apple.quarantine Contrôler et traiter de manière ciblée Peut provenir d’un outil de téléchargement ou d’un navigateur
com.apple.ResourceFork Décider selon le type d’artefact Généralement inutile pour un paquet de configuration standard, mais certains fichiers peuvent en dépendre
Paquets d’applications signés Préserver la structure et vérifier de nouveau Un nettoyage indifférencié augmente le risque d’anomalies de signature

Le nettoyage doit cibler un répertoire temporaire isolé, et non l’espace de travail contenant les sources. Ainsi, même si la politique est incorrecte, elle ne modifiera ni les caches, ni les répertoires de dépendances, ni les entrées nécessaires au build suivant.

Si le livrable contient une application signée, vérifiez d’abord la signature de l’artefact d’origine. Les documents, configurations et journaux ordinaires peuvent suivre une politique de refus des métadonnées plus stricte. N’appliquez pas la même commande de suppression récursive à ces deux catégories.

Créer un répertoire temporaire à usage unique

Le répertoire temporaire doit être réservé à la tâche en cours et supprimé à sa sortie. Ne réutilisez pas un chemin fixe comme /tmp/release, car des tâches parallèles risqueraient de s’écraser mutuellement.

#!/bin/bash
set -euo pipefail

SOURCE="${1:?source path required}"
OUTPUT="${2:?output path required}"
STAGE="$(mktemp -d "${TMPDIR:-/tmp}/bamini-artifact.XXXXXX")"
UNPACK="$(mktemp -d "${TMPDIR:-/tmp}/bamini-unpack.XXXXXX")"

cleanup() {
  rm -rf "$STAGE" "$UNPACK"
}
trap cleanup EXIT

/usr/bin/ditto --norsrc "$SOURCE" "$STAGE/payload"
find "$STAGE/payload" -type f -name '.DS_Store' -delete
find "$STAGE/payload" -type f -name '._*' -delete

mktemp attribue un répertoire différent à chaque tâche, tandis que trap couvre les sorties normales, les échecs et les interruptions. Ici, ditto --norsrc copie le contenu sans transporter volontairement les branches de ressources. Une analyse ultérieure reste nécessaire, car le répertoire d’entrée peut déjà contenir des fichiers ._ matérialisés.

Si le workflow doit livrer un paquet d’application complet, vérifiez d’abord que la stratégie de copie préserve tout ce dont l’application a besoin. La méthode la plus sûre consiste à placer séparément les paquets d’applications et les pièces jointes ordinaires dans des zones temporaires, puis à appliquer une politique adaptée à chaque catégorie.

Analyser les attributs étendus sans tout effacer

xattr -cr est pratique, mais beaucoup trop général. Cette commande supprime à la fois les attributs de quarantaine connus et les autres attributs qui n’ont pas encore été intégrés aux règles de contrôle. Le pipeline repasse alors au vert, mais la cause profonde reste masquée.

Commencez par répertorier les noms des attributs, puis bloquez la tâche uniquement sur les éléments explicitement interdits :

ATTR_REPORT="$STAGE/xattr.txt"

if /usr/bin/xattr -lr "$STAGE/payload" >"$ATTR_REPORT" 2>&1; then
  if grep -E 'com\.apple\.(quarantine|ResourceFork)' "$ATTR_REPORT"; then
    echo "disallowed macOS metadata found" >&2
    exit 41
  fi
fi

if find "$STAGE/payload" -type f \( -name '.DS_Store' -o -name '._*' \) -print -quit |
  grep -q .; then
  echo "hidden metadata files found" >&2
  exit 42
fi

Cette barrière échoue dès qu’elle détecte des métadonnées. Elle permet ainsi d’identifier l’étape qui les a introduites. Une fois leur origine confirmée, appliquez une correction ciblée pendant le téléchargement, la copie ou la génération. Si l’activité autorise réellement un attribut étendu particulier, ajoutez à la liste d’autorisation le périmètre des fichiers concernés et le nom de l’attribut, au lieu d’exempter tout le répertoire.

Consigner l’étape d’origine

Lancez une analyse après l’extraction des sources, après la compilation et après la mise en zone temporaire. La première étape où l’anomalie apparaît délimite le périmètre de l’enquête. Les sources courantes incluent la consultation de répertoires dans une interface graphique, la copie depuis un système de fichiers non natif et les outils qui téléchargent un contenu avant de le décompresser. Une analyse effectuée uniquement avant l’archivage final peut bloquer la pollution, mais elle ne permet pas d’identifier l’étape responsable.

Rouvrir et contrôler l’archive finale

Un répertoire temporaire propre ne garantit pas que l’outil d’archivage ne réintroduira pas de métadonnées. Après avoir créé le ZIP, contrôlez les noms de ses membres, puis décompressez-le dans un nouveau répertoire pour effectuer une nouvelle vérification.

rm -f "$OUTPUT"
/usr/bin/ditto -c -k --norsrc --keepParent \
  "$STAGE/payload" "$OUTPUT"

/usr/bin/unzip -Z1 "$OUTPUT" >"$STAGE/members.txt"

if grep -E '(^|/)\.DS_Store$|(^|/)\._[^/]+$' "$STAGE/members.txt"; then
  echo "archive contains forbidden metadata files" >&2
  exit 43
fi

/usr/bin/ditto -x -k "$OUTPUT" "$UNPACK"

if find "$UNPACK" -type f \( -name '.DS_Store' -o -name '._*' \) -print -quit |
  grep -q .; then
  echo "extracted artifact failed metadata check" >&2
  exit 44
fi

Le contrôle de la liste des membres est rapide et convient comme première barrière. La vérification après décompression couvre également la conversion des chemins et le comportement de l’outil d’extraction. Les deux contrôles sont nécessaires : le système d’envoi reçoit l’archive elle-même, tandis que l’utilisateur manipule finalement son contenu décompressé.

Si l’archive contient une application signée, recherchez le fichier .app après décompression et relancez une vérification stricte de sa signature. Ne contrôlez pas uniquement la copie antérieure à l’archivage, car cela ne révélerait pas les modifications provoquées par les paramètres de création de l’archive.

Intégrer la barrière à un processus de livraison reproductible

Conservez une interface de script fixe avec deux paramètres — un répertoire d’entrée et un fichier de sortie — et faites produire les éléments de preuve suivants à chaque tâche :

  1. Le chemin et le type de l’artefact avant la mise en zone temporaire.
  2. Le résultat de l’analyse des attributs étendus.
  3. La liste des membres du ZIP.
  4. Le résultat du contrôle des fichiers cachés après décompression.
  5. Le résultat de la seconde vérification de signature lorsqu’un paquet d’application est présent.
  6. L’empreinte SHA-256 de l’archive finale.

L’empreinte peut être générée avec shasum -a 256 artifact.zip. Elle ne prouve pas que le contenu de deux fichiers ZIP est sémantiquement identique, mais elle permet de confirmer qu’aucun octet n’a changé pendant l’envoi, le téléchargement ou la transmission.

Pour exécuter ce type de tâche sur un Mac cloud BAMini, commencez par vérifier dans la console les configurations actuellement disponibles. Placez ensuite le script dans le dépôt et faites-le appeler par la CI, plutôt que de compter sur un nettoyage manuel dont un membre de l’équipe devrait se souvenir. Après l’échec d’une barrière, conservez la liste des membres et le rapport des attributs, mais supprimez les répertoires temporaires contenant des données du projet. Chaque nouvelle tâche doit créer un nouveau répertoire temporaire afin que les résidus de l’exécution précédente ne faussent pas le résultat.

L’objectif final n’est pas de faire disparaître tous les attributs étendus, mais de garantir que le livrable contient uniquement les éléments explicitement approuvés par l’équipe. L’isolation de la zone temporaire limite la portée des modifications, les analyses par étapes permettent d’en localiser l’origine, et la vérification après décompression valide le résultat réellement livré. Ces trois mesures doivent être réunies pour empêcher les métadonnées cachées de réapparaître au fil des différents chemins de copie.

Questions fréquentes

Faut-il exécuter xattr -cr sur tout le répertoire de travail ?

Non. Cette commande supprime récursivement tous les attributs étendus, y compris des resource forks utiles, et peut masquer un défaut en amont. Limitez le nettoyage à un staging isolé.

Pourquoi des fichiers ._ subsistent-ils après la suppression de .DS_Store ?

Les fichiers ._ sont des fichiers annexes AppleDouble, distincts de .DS_Store. Désactivez la copie des resource forks lors de l’empaquetage, puis contrôlez la liste complète de l’archive.

Quand faut-il vérifier une application signée ?

Vérifiez d’abord l’application source, puis copiez-la dans le staging sans nettoyage global de ses attributs. Après empaquetage, extrayez-la ailleurs et vérifiez de nouveau strictement sa signature.

Nœud physique dédié

Placez votre prochaine compilation dans le cloud sur un Mac mini

Choisissez la configuration, la durée de facturation et la région du nœud pour exécuter vos tâches de développement, de compilation et d’automatisation sur une machine physique dédiée.

Louer un Mac mini maintenant