Sur un Mac cloud utilisé durablement pour l’archivage et les tests automatisés, les incidents les plus courants ne viennent pas nécessairement du code. Xcode écrit en continu dans DerivedData, les archives, les fichiers de prise en charge des appareils et les données des simulateurs. Lorsque le disque approche de la saturation, le compilateur peut signaler des erreurs d’écriture sans rapport avec le problème réel, tandis que l’étape de signature peut ne laisser que des artefacts incomplets. La bonne approche ne consiste pas à vider périodiquement tous les répertoires, mais à mesurer d’abord l’espace occupé, à mettre en place un seuil bloquant avant les builds, puis à nettoyer par étapes selon la facilité de récupération des données.
Établir d’abord une référence d’utilisation du disque
Commencez par relever l’espace disponible sur le système, puis examinez les répertoires de développement. df indique la capacité encore disponible pour les écritures sur le système de fichiers, tandis que du permet d’identifier ce qui occupe l’espace. Ces deux commandes ne sont pas interchangeables.
df -Pk /
for path in \
"$HOME/Library/Developer/Xcode/DerivedData" \
"$HOME/Library/Developer/Xcode/Archives" \
"$HOME/Library/Developer/CoreSimulator" \
"$HOME/Library/Developer/Xcode/iOS DeviceSupport"
do
if [ -e "$path" ]; then
du -sk "$path"
fi
done
Il est recommandé d’effectuer une mesure avant un build propre, une autre après la création de l’archive et une dernière à la fin des tests. Ces trois valeurs permettent de quantifier la croissance liée à une tâche et d’éviter de confondre un pic normal avec une fuite d’espace disque. Pour repérer ensuite les répertoires les plus volumineux dans DerivedData, exécutez :
du -sk "$HOME/Library/Developer/Xcode/DerivedData"/* 2>/dev/null \
| sort -nr \
| head -20
L’espace disponible affiché par APFS peut être influencé par les données purgeables. Le contrôle préalable d’un build doit s’appuyer sur les blocs disponibles rapportés par
df, et non sur la seule taille apparente des répertoires pour conclure que la tâche pourra aller jusqu’au bout.
Définir un seuil de capacité explicite pour les builds
Le seuil de capacité doit être déterminé à partir des pics réellement mesurés, et non fixé arbitrairement selon une règle empirique. Commencez par 30 Go et relevez l’espace disponible minimal pendant l’intégralité d’un archivage. Après plusieurs exécutions stables, ajustez le seuil à 1,5 fois l’augmentation maximale observée, en ajoutant la capacité nécessaire aux artefacts exportés.
Le script suivant peut être placé au tout début du pipeline. Si l’espace est insuffisant, il se termine avec le code d’état 75, afin que l’ordonnanceur considère la tâche comme temporairement inexécutable au lieu de lancer un build qui a de fortes chances d’échouer.
#!/bin/zsh
set -euo pipefail
minimum_kb=$((30 * 1024 * 1024))
available_kb=$(df -Pk / | awk 'NR == 2 {print $4}')
if (( available_kb < minimum_kb )); then
printf 'Insufficient disk capacity: %s KB available
' "$available_kb"
exit 75
fi
printf 'Disk capacity check passed: %s KB available
' "$available_kb"
Le seuil doit être enregistré séparément pour chaque nœud. Les pics varient selon la version de Xcode, la combinaison de simulateurs et la taille du projet. Les résultats obtenus sur un petit projet ne doivent pas servir de référence pour un vaste espace de travail.
Isoler les données de chaque build dans un répertoire dédié
Le partage du répertoire DerivedData par défaut ne pose pas seulement un problème de capacité : il empêche également de déterminer à quelle tâche appartient chaque répertoire. En attribuant un chemin distinct à l’espace de travail, il devient possible de supprimer précisément les données concernées à la fin de la tâche, sans perturber les autres builds en cours.
job_root="$HOME/build-jobs/$BUILD_ID"
derived_data="$job_root/DerivedData"
archive_path="$job_root/artifacts/App.xcarchive"
mkdir -p "$job_root/artifacts"
xcodebuild \
-workspace App.xcworkspace \
-scheme App \
-configuration Release \
-derivedDataPath "$derived_data" \
-archivePath "$archive_path" \
archive
BUILD_ID doit être fourni par le système de gestion des tâches et limité aux lettres, chiffres, points, traits de soulignement et traits d’union. Avant tout nettoyage, vérifiez également que le chemin ciblé se trouve bien sous build-jobs, afin qu’une variable vide n’étende pas la suppression au répertoire personnel.
Nettoyer par niveaux selon la facilité de récupération
Le nettoyage doit commencer par les données qui peuvent être régénérées et ne traiter qu’en dernier les archives nécessitant une validation humaine.
| Niveau | Données | Action recommandée | Principale limite |
|---|---|---|---|
| 1 | DerivedData des tâches terminées | Supprimer par répertoire de tâche | Vérifier qu’aucun processus de build ne les utilise |
| 2 | Simulateurs devenus indisponibles | Nettoyer avec simctl |
Ne pas supprimer directement le répertoire Devices |
| 3 | Anciens fichiers de prise en charge des appareils | Vérifier selon les versions réellement testées | Conserver les versions du système encore nécessaires au débogage |
| 4 | xcarchive et dSYM | Les déplacer après validation humaine | Garantir la traçabilité des versions publiées |
La suppression des simulateurs indisponibles doit être confiée à l’outil système :
xcrun simctl delete unavailable
Ne videz pas directement CoreSimulator/Devices. Si l’état du répertoire de fichiers ne correspond plus à celui du service de simulateurs, des problèmes encore plus difficiles à diagnostiquer apparaîtront lors de la création et du démarrage des appareils. Il ne faut pas non plus supprimer automatiquement les archives au seul motif qu’elles dépassent un certain âge : un fichier xcarchive peut contenir le dSYM correspondant à une version publiée. La procédure correcte consiste à enregistrer d’abord la version, le numéro de build et l’emplacement de destination, puis à supprimer la copie locale.
Éviter trois pièges lors du nettoyage automatisé
Premièrement, ne nettoyez jamais un répertoire partagé pendant un build. Même s’il paraît ancien, un fichier peut encore être référencé par le compilateur via un index ou un artefact intermédiaire. La tâche de nettoyage doit obtenir un verrou à l’échelle du nœud ou se limiter aux répertoires de travail isolés qui ont été explicitement marqués comme terminés.
Deuxièmement, ne confondez pas « suppression réussie » et « espace effectivement libéré ». Après la suppression, exécutez de nouveau df -Pk / pour confirmer que le nombre de blocs disponibles a réellement augmenté. Si ce n’est pas le cas, recherchez les fichiers encore ouverts par des processus au lieu de relancer les commandes de suppression.
Troisièmement, ne laissez pas un script décider seul de l’importance d’une archive. Une tâche sans surveillance doit uniquement dresser la liste des éléments candidats, par exemple en indiquant la taille du répertoire, la date de dernière modification et le numéro de build associé. La décision de déplacer ou de supprimer ces éléments doit dépendre des registres de publication.
Valider le résultat avec un build reproductible
Une fois le nettoyage terminé, exécutez au moins un archivage identique à la tâche de production. Pendant la validation, consignez la capacité initiale, la capacité minimale, la capacité finale, le chemin de l’archive et l’état de sortie, puis vérifiez que le fichier .xcarchive a été généré dans son intégralité. Si le nœud exécute également des tests sur simulateur, démarrez une fois chaque version conservée dans la matrice de tests afin de confirmer que les appareils peuvent être créés, démarrés et arrêtés normalement.
La liste de contrôle finale peut rester concise : le seuil préalable au build a été validé ; la tâche utilise un DerivedData isolé ; aucun processus de compilation ne subsiste après sa fin ; les archives et les dSYM ont été enregistrés ; simctl list ne contient aucun appareil anormal ; l’espace disque restant dépasse le seuil requis pour la prochaine tâche. Le cycle de nettoyage n’est complet que lorsque toutes ces conditions sont réunies.
Questions fréquentes
Quel espace libre faut-il conserver avant un build Xcode ?
Il n’existe pas de valeur universelle. Commencez avec un seuil de 30GB, mesurez le pic d’une archive complète, puis réservez au moins 1,5 fois ce pic pour un grand projet composé de nombreux modules.
Peut-on supprimer tout le dossier DerivedData ?
Oui, à condition qu’aucun build actif ne l’utilise. Il est plus sûr d’attribuer un DerivedDataPath à chaque espace de travail et de ne supprimer que les répertoires des tâches terminées.
Quelles données Xcode faut-il exclure du nettoyage automatique ?
Excluez les archives en cours, les xcarchive non sauvegardées, les dSYM associés aux versions publiées et les appareils de simulation encore utilisés par la matrice de tests.
Conserver un environnement reproductible sur le même Mac dans le cloud
Choisissez un modèle, une région et une durée de location fixes, puis utilisez l’interface graphique complète de macOS et la ligne de commande pour vos tâches de développement ou d’automatisation.