L’intégration continue iOS à échelle
[Version actualisée en 2023]
Si vous développez des applications iOS (ou macOS) de manière professionnelle, vous utilisez sans doute un outil d’intégration continue pour automatiser les tests, la signature et la mise à disposition de vos applications. Or tous ceux qui se sont frottés à la mise en place et à la maintenance de ce type de chaîne vous le dirons : l’intégration continue dans l’univers Apple, ce n’est pas simple !
L’intégration continue
Une intégration continue, c’est un petit peu le chef d’orchestre qui va permettre d’automatiser les actions techniques répétitives, pour gagner du temps, mais aussi pour fiabiliser le processus de livraison.
Fonctionnement
Une plateforme d’intégration continue est toujours structurée de la même manière :
Le maître centralise les paramètres et déclenche les traitements sur les runners appropriés.
Les runners mettent à disposition un environnement nécessaire à l’exécution des traitements demandés. Ils sont composés d’un OS et d’un nombre plus ou moins important d’outils complémentaires pour compiler, tester, analyser, ou déployer les applications.
Un runner possède un nombre de slots limité (nombre de jobs qu’il peut traiter en parallèle) que l’on détermine en fonction de ses capacités matérielles de traitement et de stockage (CPU, RAM, espace disque).
Pour augmenter la capacité de traitement d’une intégration continue, il faut donc soit procéder à des mises à jour de son matériel, soit rajouter des runners supplémentaires.
Types de jobs
Une plateforme d’intégration continue intervient généralement à 3 niveaux dans la phase de développement :
- la compilation continue, consiste à minima à re-compiler et re-tester (en rejouant au moins les tests unitaires) l’intégralité de l’application à chaque modification de la base de code, afin de détecter au plus tôt les erreurs et régressions.
- l’analyse, consiste à périodiquement compiler, exécuter les tests (tous) et lancer les divers outils d’analyse afin de générer des métriques relatives à la qualité de l’application (code, performances, sécurité…).
- la livraison, automatique (publication de modifications sur une branche du dépôt de code source), ou déclenchée manuellement permet de signer (étape obligatoire pour le déploiement, même en mode test, d’une application iOS) et publier l’application sur “store” (plateforme de distribution) qui permettra aux testeurs (ou utilisateurs finaux selon le cas) de récupérer l’application.
L’intégration continue pour iOS
Les étapes décrites précédemment misent bout à bout permettent de définir une intégration continue type pour iOS, comme le décrit le schéma ci-dessous :
Ce schéma, en plus de décrire les étapes d’une intégration continue pour iOS, détaille les outils mis en oeuvre classiquement pour réaliser les traitements nécessaires.
Cela permet de constater qu’Apple fournit le strict minimum pour construire une chaîne d’intégration continue.
En effet, alors que sur les autres plateformes (Android, web) des outils de gestion de build / task runners permettent de faciliter l’automatisation de chaque étape, sur iOS, il faut jongler avec plusieurs outils en ligne de commande (dont une partie a été écrite par la communauté pour combler les manques) pour arriver à ses fins.
Ce n’est donc pas simple de mettre en place une intégration continue complète et fiable sur iOS et cela à des impacts directs sur la solution d’intégration continue utilisée, comme sur la maintenance de celle-ci (mises à jour, augmentation des capacités).
Il est recommandé un audit technique en amont pour déterminer les axes d'amélioration en terme d'intégration continue.
Xcode cloud: la solution Apple
Depuis 2022 Apple propose sa propre solution d’intégration continue intégrée à Xcode: Xcode cloud.
Cette solution, à part des autres, permet de prendre en charge les tâches d’intégration continue pour les appareils Apple relativement simplement, sans sortir d’Xcode.
Parmi ses avantages: une solution sans maintenance, qui ne nécessite aucune compétence DevOps, et avec des tarifs plus compétitifs que Bitrise.
Mais il y’a également quelques inconvénients: un outil moins flexible que les intégrations continues plus classiques, et qui ne permet d’adresser que les appareils Apple (ce qui nécessite de se doter d’une autre CI pour traiter les autres plateformes).
Les autres solutions du marché
Le nombre de solutions d’intégration continue ne cesse d’augmenter. Cependant, il est possible de les classer selon 3 catégories par rapport à leur support ou capacité à supporter iOS.
Les solutions “Full Saas”
Les solutions “Full Saas”, permettent d’externaliser l’intégralité de sa chaîne d’intégration continue Apple (maître et runners) dans le cloud et donc de s’affranchir des contraintes matérielles et de la maintenance de celle-ci.
Exemples : Bitrise, CircleCI.
Les solutions “On Premises”
Solutions classiques ou toute la chaîne est installée localement (maître et runners), qui permettent un contrôle total, mais nécessitent une maintenance plus lourde, et l’achat de Macs pour construire ses runners.
Exemples : Jenkins, TeamCity.
Les solutions “Hybrides”
Les solutions “Hybrides” sont un mélange des 2 précédentes, c’est à dire des solutions Saas mais qui ne fournissent pas de support pour les environnements Apple et pour lesquelles il faut connecter ses propres Mac pour disposer du support des environnements Apple (le maître et éventuellement des runners de type Linux sont proposés en Saas, mais l’ajout de runners spécifiques est possible).
Exemple : GitLab CI (gitlab.com).
Critères de choix
Chaque solution possède ses avantages et inconvénients.
Ci-dessous, un tableau récapitulatif qui vous permettra d’y voir plus clair :
Dans le cas ou vous disposez déjà d’une plateforme d’intégration continue pour d’autres technologie que le mobile (web front, back par exemple). Il peut aussi être intéressant de prendre en compte sa capacité à supporter le mobile.
En effet, l’utilisation d’une seule plateforme d’intégration continue vous permettra d’économiser du temps de maintenance et de simplifier son exploitation.
Gestion de runners multiples
Si une solution de type Full Saas n’est pas appropriée pour votre usage, vous devrez gérer vos runners par vous même.
Maintenance complexe
Quand il y en a un seul : cela reste relativement simple, mais il est fort possible qu’un seul ne vous suffise pas pour traiter en temps et en heure toutes les sollicitations (notamment les demandes de livraisons intermédiaires de dernière minute).
En effet, au delà d’un seul runner à gérer pour iOS, le temps de maintenance augmente considérablement, puisque vous devrez synchroniser vos scripts et outils sur 2 machines différentes : c’est un travail manuel laborieux et répétitif, qui risque en plus d’induire des disparités entre vos runners au moindre écart (et produire des comportements aléatoires dans votre chaîne d’intégration continue).
Automatiser la gestion des runners
Pour simplifier, accélérer, et fiabiliser cette maintenance, la plupart des runners sont construits sous forme de conteneurs Dockers, puisque ce format permet de facilement scripter la création d’environnements, de les construire et de les déployer.
Hélas, Docker ne sais pas conteneuriser macOS…
La solution se rapprochant le plus est donc le provisioning automatique de machine virtuelle en utilisant Vagrant et VirtualBox (ou VMWare).
Vagrant est un outil permettant de scripter la création d’une machine virtuelle (c’est à dire : installation d’une image de base incluant le système d’exploitation + l’ajout d’outils supplémentaires).
VirtualBox et VMWare sont quand à eux, 2 solutions de virtualisation (capable d’exécuter des machines virtuelles) disponibles sous macOS.
Certes, cette solution est plus lourde que Docker (temps de création des machines plus long, occupe plus d’espace disque, performances moindres du fait de la virtualisation), mais en garde tout de même le bénéfice principal, à savoir : fiabiliser et automatiser la création de machines / runners.
A toutes fins utiles, je mets à disposition ici un script Vagrant permettant de créer un runner pour GitLab CI en une seule ligne de commande. Libre à vous de le compléter ou de le modifier pour l’adapter à votre usage.
En conclusion…
L’intégration continue est un outil indispensable pour la production d’applications mobiles dans un environnement professionnel : il est important de considérer les diverses solutions existantes pour construire une plateforme qui réponde à ses besoins et contraintes.
Il ne faut pas non plus négliger les efforts de maintenance nécessaires à son fonctionnement : elle doit en permanence être mise à jour pour intégrer de nouvelles fonctionnalités ou pour supporter les dernières versions des outils de compilation.
La mise en place d’une intégration continue sur iOS peut se révéler assez complexe en fonction de son environnement. En outre, elle nécessite des machines de type Mac pour fonctionner.
Si vos besoins en intégration continue vous amènent à mettre en place plusieurs runners iOS, ayez recours à la virtualisation pour simplifier leur gestion.
Notez que j’ai volontairement orienté cette article sur l’intégration continue pour iOS : ce n’est pas dans le but d’ignorer Android, mais parce que vous l’aurez compris : c’est la plus complexe et manuelle à mettre en place (la compilation d’une application Android peut se faire dans un conteneur Docker, et nécessite uniquement l’installation du SDK pour fonctionner).
Important : si vous développez des applications avec des technologies cross-platform (React Native ou Futter) , sachez que des chaînes d’intégration continue iOS et Android restent nécessaires pour compiler sur les plateformes cible.
FAQ
Qu'est-ce que l'intégration continue pour iOS ?
L'intégration continue pour iOS est un processus automatisé qui permet de compiler, tester et déployer des applications iOS. Elle agit comme un chef d'orchestre qui automatise les tâches techniques répétitives pour gagner du temps et fiabiliser le processus de livraison.
Quels sont les principaux types de jobs dans l'intégration continue iOS ?
Il existe trois niveaux principaux - la compilation continue (pour détecter rapidement les erreurs), l'analyse (pour évaluer la qualité du code), et la livraison (pour signer et publier l'application).
Pourquoi l'intégration continue est-elle complexe sur iOS ?
L'intégration continue sur iOS est complexe car Apple fournit le minimum d'outils nécessaires. Contrairement à d'autres plateformes, il faut utiliser plusieurs outils en ligne de commande différents, dont certains développés par la communauté, pour créer une chaîne d'intégration complète.
Comment fonctionne une plateforme d'intégration continue ?
Une plateforme d'intégration continue est composée d'un maître qui centralise les paramètres et déclenche les traitements, et de runners qui fournissent l'environnement nécessaire à l'exécution des tâches. Les runners ont une capacité limitée de traitement en parallèle.