Les défis de l’intégration et du déploiement continus pour les applications mobiles

Pour permettre de déployer des applications en production de manière toujours plus fréquente, tout en garantissant un niveau de qualité optimal, les grands du Web ont formalisé un ensemble de bonnes pratiques connues sous le nom d’intégration et de déploiement continus. En retenant ces meilleures pratiques DevOps, de nombreux géants du Web sont aujourd’hui en mesure d’effectuer plusieurs centaines de déploiement en production par jour de manière sécurisée, contre quelques mises en production fastidieuses par semaine ou par mois il y a encore quelques années.

L’intégration et le déploiement continus, plus communément appelé CI/CD (Continuous Integration / Continuous Delivery), sont des pratiques qui permettent d’automatiser toutes les phases de déploiement d’une application, à l’aide d’une plate forme d’intégration continue, depuis la vérification de la qualité du code source jusqu’à la production du livrable final en passant par l’application des tests unitaires, et ce de manière automatique suite à chaque modification du code source.

Orchestrateur

Un orchestrateur est une plateforme nous permettant, selon un langage spécifique, de définir un certain nombre de taches à exécuter sous forme de pipeline, séquentiellement ou en parallèle.

Nous utiliserons ici la solution Open Source de référence Jenkins déployée sur notre infrastructure CaaS sur AWS, mais il existe de nombreuses alternatives comme TravisCI ou CircleCI par exemple.

 

Dans le cadre du développement d’une application dite classique (site web ou API par exemple), la mise en place de ce système se fait relativement sans encombre. Les différentes étapes nécessaires à la construction, à la validation et au déploiement de ce type de solution sont assez facilement industrialisables en tirant profit de solutions éprouvées du marché.

En revanche, l’adaptation d’un pipeline « classique » en pipeline adapté pour une application mobile devient tout de suite plus complexe. Les principaux écueils sont les suivants :

  • Pour les applications iOs, Apple impose d’utiliser un poste MacOs pour construire les applications.
  • La nature même des applications mobiles diffère des applications Web classiques. En effet, alors qu’une application web peut être construite une seule fois et déployée sur n’importe quel environnement à l’aide d’un simple changement de configuration applicative (on parle de package applicatif invariant), les applications mobiles doivent être reconstruites en fonction de l’environnement sur lequel elles doivent être déployées (développement, recette, production par exemple).
  • L’application de tests automatisés n’est pas aussi facile que sur navigateur Web où des solutions de type Selenium sont déjà largement répandues.
  • La publication des applications sur les différents store publics passent par des étapes de validation qui ralentissent le rythme de livraison.
  • La publication des applications nécessite également de manipuler un ensemble de clés de chiffrement qui prouvent la provenance et l’intégrité de l’application mobile.

Exploration des différentes alternatives

CACD2 a donc étudié plusieurs pistes afin de pallier à ces différents problèmes.

Une des solutions possibles aurait été d’installer un poste de travail MacOs, connecté à internet, servant uniquement de slave Jenkins et de maitriser de bout en bout la compilation d’un projet iOS à l’aide d’un pipeline Jenkins spécifique. Mais l’exploitation quotidienne de ce poste de travail peut se révéler fastidieuse sur la durée. De plus, le fait que l’OS MacOs ne soit pas virtualisable nous pose une problématique de scalabilité.

Nous avons donc décidé de regarder d’un peu plus près les solutions SaaS (Software as a Service) spécialisées nous permettant d’automatiser ces différentes opérations. Ici, le matériel MacOs étant mis à disposition par le fournisseur Cloud, le problème de scalabilité et de maintenance n’intervient plus.

Après quelques recherches, nous nous sommes arrêtés sur Bitrise, une solution SaaS qui fournit tout type d’environnement (Linux ou MacOs) pour permettre la construction des applications Android et iOS, et ce quelle que soit la nature du projet (projet natif Swift / Java / Kotlin, React Native, Cordova / PhoneGap, Xamarin …). La prise en main de l’outil s’est avérée relativement simple grâce à leurs APIs et leurs documentations de qualité.

La question du périmètre de responsabilité à confier à Bitrise s’est alors soulevée. Nous pourrions en effet décider de lui laisser gérer l’intégralité du pipeline CI/CD de l’application depuis la compilation jusqu’à la publication en passant par les tests unitaires… Mais ce choix entrainerait une dépendance éditeur trop importante et ne tirerait plus profit de notre environment CI/CD Jenkins qui est le cœur de notre infrastructure.

Nous avons donc décidé de faire un compromis, et de prendre le meilleur des deux solutions, en mettant en place un pipeline Jenkins qui délègue uniquement la construction des binaires à Bitrise. Cette solution nous permet de garder le contrôle et une certaine cohérence entre nos pipelines mobile et web.

Le pipeline CI/CD mobile construit par CACD2

Chaque pipeline est composé de plusieurs étapes qui s’appuient sur des building blocks éventuellement interchangeables. Ainsi, potentiellement, la brique liée a la génération de l’application (via Bitrise) pourrait être substituée à tout moment par une autre implémentation.

Une fois le pipeline Jenkins relié au dépôt GIT, pour chaque commit de l’équipe de développement, le pipeline associé se met en oeuvre et exécute les tâches suivantes :

  • Tests de sécurité et de qualité sur le code source à l’aide de l’outil SonarQube
  • Lancement de la construction de l’application par Bitrise à l’aide d’un appel de service. Bitrise se charge alors des activités suivantes :
    • Compiler / générer l’application sur une machine virtuelle provisionnée spécifiquement pour ce build
    • Exécuter les tests unitaires
    • Packager l’application sous forme de paquet IPA ou APK
    • Mettre à disposition les binaires de l’application dans un espace temporaire pour récupération par l’orchestrateur Jenkins
  • Récupération et archivage des binaires de l’application sur un bucket S3 AWS
  • Lancement des tests de bout en bout
    • Ici, nous faisons appel à un second pipeline Jenkins qui utilise une ferme de périphériques virtuels chez Amazon (AWS Device Farm) afin de tester l’application sur un jeu de périphériques.
    • Les tests Appium sont décrits en langage naturel à l’aide de l’outil Cucumber, permettant ainsi de bénéficier d’une réelle lisibilité du patrimoine de tests automatisés.
  • Envoi d’une notification aux personnes intéressées (par mail, slack, etc…) via AWS SNS (Amazon Simple Notification Service) pour avertir de la disponibilité de la nouvelle application construite.

Intentionnellement, nous n’avons pas étendu le pipeline jusqu’à la publication des applications dans les stores publics. En effet, ces étapes nécessitent d’avoir à disposition les certificats utilisés par nos différents clients. Etant donné que ces étapes ne sont pas exécutées à une fréquence très élevée, le coût d’industrialisation de ces dernières étapes ne nous semblait pas pertinent.

Conclusion

Après plusieurs tentatives, nous avons été agréablement surpris par les solutions de type SaaS, en particulier Bitrise, pour industrialiser le développement d’application mobiles. Afin de limiter la dépendance éditeur, nous avons construit une architecture modulaire, construite autour de pipelines Jenkins, qui délègue la construction des binaires de l’application à Bitrise. Le reste de l’ordonnancement est intégralement géré par Jenkins, à l’image de ce que nous appliquons pour l’industrialisation des applications Web.

Nous arrivons aujourd’hui à un niveau d’industrialisation sur notre PIC mobile tout aussi avancé que celui de notre PIC classique. Cette industrialisation nous permet de développer rapidement des applications mobiles dont le niveau de qualité est surveillé en continu par notre plateforme.


Ressources:

Jenkins : https://jenkins.io/doc/

Bitrise : https://devcenter.bitrise.io

AWS S3 : https://aws.amazon.com/documentation/s3/

AWS DeviceFarm : https://aws.amazon.com/documentation/devicefarm/

AWS SNS : https://aws.amazon.com/documentation/sns/