Une équipe peut archiver son application sans problème après la mise à jour de dépendances, puis découvrir juste avant la publication qu’un nouveau composant ne figure pas dans l’inventaire des licences open source. Le problème vient rarement de la compilation, mais plutôt de la dispersion des sources de dépendances : SwiftPM possède son fichier de verrouillage, CocoaPods utilise une autre arborescence, et le dépôt peut aussi contenir du code source copié directement ou des paquets binaires. Exécuter ce contrôle dans une CI Mac dans le cloud permet de générer l’inventaire, de le comparer à la politique établie et de conserver les preuves dans un espace de travail fixe, au lieu de demander au responsable de la publication d’examiner les répertoires au dernier moment.
Définir les questions auxquelles le contrôle doit répondre
Un contrôle exploitable doit répondre à au moins quatre questions : quels composants cette build a-t-elle réellement résolus, quelles versions ou révisions utilise-t-elle, où se trouve le texte intégral de chaque licence, et ces conditions ont-elles déjà été approuvées ? Il ne suffit pas de rechercher des noms de fichiers avant d’autoriser la publication. La présence d’un fichier LICENSE ne garantit ni que son contenu est resté inchangé, ni que le composant est effectivement lié à la cible actuelle.
Il est recommandé de produire séparément un inventaire exploitable par les machines et un rapport destiné aux personnes. L’inventaire, au format JSON, enregistre le nom du composant, sa source, sa version verrouillée, le type de licence, l’empreinte du texte et le chemin de découverte. Le rapport, au format Markdown, présente les éléments ajoutés, supprimés ou modifiés. Les deux doivent être conservés comme artefacts du pipeline.
Le contrôle vérifie que les dépendances constatées respectent la politique établie. Lorsqu’un élément inconnu est détecté, la publication doit être interrompue et une vérification demandée, sans déduire automatiquement la marche à suivre à partir du seul nom de la licence.
Inventorier les dépendances réellement utilisées par la build
Commencez par laisser Xcode résoudre les dépendances, puis analysez les répertoires effectivement utilisés par l’espace de travail. Cela évite d’inclure d’anciens caches présents sur la machine d’un développeur. Chaque tâche doit disposer de son propre DerivedData, qui sera supprimé une fois la tâche terminée.
set -euo pipefail
ROOT="$(pwd)"
OUT="$ROOT/build/license-audit"
DD="$ROOT/build/DerivedData"
mkdir -p "$OUT"
xcodebuild \
-workspace App.xcworkspace \
-scheme App \
-resolvePackageDependencies \
-derivedDataPath "$DD"
find "$DD/SourcePackages/checkouts" \
-maxdepth 3 \
-type f \
\( -iname 'license*' -o -iname 'copying*' -o -iname 'notice*' \) \
-print0 | sort -z > "$OUT/swiftpm-license-files.bin"
find "$ROOT/Pods" \
-maxdepth 4 \
-type f \
\( -iname 'license*' -o -iname 'copying*' -o -iname 'notice*' \) \
-print0 | sort -z > "$OUT/pods-license-files.bin"
Pour les dépendances binaires, l’extension du fichier ne suffit pas. Il faut également consigner l’identifiant interne du composant associé à l’URL de téléchargement, sa somme de contrôle, sa version et les déclarations fournies avec le paquet. Pour le code source copié dans le dépôt, maintenez un fichier compliance/manual-components.json qui indique clairement le propriétaire de chaque répertoire, afin que chaque analyse ne dépende pas de correspondances approximatives.
Enregistrer également tous les fichiers de verrouillage
Copiez Package.resolved, Podfile.lock et l’inventaire manuel des composants dans le répertoire du rapport. Le contrôle doit vérifier que chaque composant de l’inventaire correspond à une source verrouillée. Inversement, il doit aussi confirmer qu’aucune dépendance directe présente dans les fichiers de verrouillage n’a disparu du rapport. Si le projet contient plusieurs espaces de travail, chacun doit être résolu séparément ; contrôler uniquement l’application principale ne suffit pas.
Normaliser les licences et calculer leurs empreintes
Les textes de licence ne diffèrent souvent que par leurs sauts de ligne ou leurs espaces de fin de ligne. Avant de calculer le SHA-256, vous pouvez les convertir en UTF-8, uniformiser les sauts de ligne au format LF et supprimer les espaces en fin de ligne. Ne supprimez pas les paragraphes du texte, les mentions de copyright ni les années, car cela masquerait de véritables modifications.
python3 - <<'PY'
from pathlib import Path
import hashlib
import json
root = Path("build/license-audit/licenses")
rows = []
for path in sorted(root.rglob("*")):
if not path.is_file():
continue
text = path.read_text(encoding="utf-8", errors="strict")
normalized = "\n".join(line.rstrip() for line in text.splitlines()).strip() + "\n"
digest = hashlib.sha256(normalized.encode("utf-8")).hexdigest()
rows.append({"path": str(path), "sha256": digest})
Path("build/license-audit/license-hashes.json").write_text(
json.dumps(rows, ensure_ascii=False, indent=2) + "\n",
encoding="utf-8"
)
PY
Le type de licence et l’empreinte du texte doivent être enregistrés séparément. Le type sert à appliquer la politique, tandis que l’empreinte permet de détecter les modifications discrètes effectuées en amont. Si la licence ne peut pas être identifiée de manière fiable, marquez-la comme UNKNOWN ; un nom de fichier familier ne justifie jamais un classement automatique.
Gérer les changements avec une politique versionnée
Le fichier de politique doit être placé sous contrôle de version et modifié selon un processus de revue de code clairement défini. Vous pouvez associer les états allow, review et deny aux identifiants de licence, tout en enregistrant les empreintes de texte approuvées pour certains composants. Il est recommandé d’évaluer les résultats comme suit :
| Situation | Résultat de la CI | Action suivante |
|---|---|---|
| Composant connu, version et texte inchangés | Réussite | Conserver le rapport |
| Nouvelle version, empreinte de licence inchangée | Vérification | Confirmer les modifications du composant |
| Nouveau composant ou licence inconnue | Blocage | Ajouter la provenance et l’approbation |
| Modification du texte de licence d’un composant existant | Blocage | Comparer le texte intégral |
| Composant présent dans le fichier de verrouillage mais absent du rapport | Blocage | Corriger les règles de découverte |
Une liste d’autorisation ne doit pas se limiter à des catégories générales. Un composant peut inclure un fichier NOTICE supplémentaire, une double licence ou une autorisation distincte pour certaines ressources. Le rapport doit donc conserver tous les fichiers pertinents. Pour les paquets binaires, il faut également vérifier que la somme de contrôle du téléchargement actuel correspond à l’enregistrement approuvé.
Intégrer le rapport aux processus de fusion et de publication
Les demandes de fusion courantes peuvent exécuter la résolution des dépendances, la comparaison des changements et la génération du rapport. La tâche de publication doit en plus vérifier le contenu de l’archive afin de confirmer que l’artefact final correspond au même fichier de verrouillage. Il est recommandé de stocker la référence dans compliance/license-baseline.json et de demander à la CI de comparer uniquement des champs structurés, plutôt que la sortie colorée du terminal.
En cas d’échec du contrôle, les journaux doivent indiquer directement le composant, l’ancienne valeur, la nouvelle valeur et le chemin vers la preuve, au lieu de renvoyer uniquement « échec du contrôle des licences ». Le répertoire du rapport doit contenir au minimum des copies des fichiers de verrouillage, les textes normalisés, l’inventaire des empreintes, la version de la politique et un résumé des différences. Sur ArmCLI, chaque tâche exécutée en parallèle doit utiliser son propre répertoire de travail afin qu’une mise à jour de dépendances dans une tâche ne contamine pas les résultats d’analyse d’une autre.
Vérifications avant la mise en production
Avant la publication, vérifiez que la résolution des dépendances n’a utilisé aucun chemin local non consigné, que toutes les dépendances directes et transitives possèdent une version et une provenance, que le nombre de licences inconnues est égal à zéro, que les répertoires de l’inventaire manuel existent toujours, que le rapport et l’archive reposent sur le même commit, et que les artefacts de CI ne contiennent aucun jeton d’accès, aucune URL de téléchargement privée ni aucune variable d’environnement non expurgée.
Cette procédure ne sert pas seulement à produire une page de déclarations : elle transforme chaque modification de dépendance en événement d’ingénierie vérifiable. Tant que les fichiers de verrouillage, les empreintes de licence et la référence de politique restent synchronisés, l’équipe peut détecter les problèmes dès l’arrivée d’une dépendance dans la branche de publication, au lieu de devoir retracer son origine une fois l’archivage terminé.
Questions fréquentes
Vérifier uniquement Package.resolved suffit-il ?
Non. Ce fichier fixe les versions SwiftPM, mais il ne garantit pas la présence des licences et ne couvre ni CocoaPods, ni le code copié dans le dépôt, ni les dépendances binaires.
Quels changements doivent bloquer une livraison ?
Une nouvelle dépendance sans licence, une condition absente de la liste autorisée, un écart avec les fichiers de verrouillage ou un texte de licence modifié doivent déclencher une revue manuelle.
Préparez votre prochain build sur un Mac physique dédié
Choisissez le modèle, le centre de données et la durée selon votre tâche. Les nœuds restent opérationnels toute l’année ; leur disponibilité réelle est indiquée en temps réel dans la console.