ProHoster > Blog > administration > Expérience CICD mobile : une norme fastlane pour de nombreuses applications mobiles
Expérience CICD mobile : une norme fastlane pour de nombreuses applications mobiles
J'aimerais parler de l'intégration et de la livraison continues d'applications mobiles utilisant Fastlane. Comment nous implémentons le CI/CD sur toutes les applications mobiles, comment nous y sommes arrivés et que s'est-il passé au final.
Il y a déjà suffisamment de matériel sur le réseau sur l'outil, ce qui nous manquait tellement au début, c'est pourquoi je ne décrirai délibérément pas l'outil en détail, mais me référerai uniquement à ce que nous avions alors :
Contexte de l’émergence du CI/CD mobile dans l’entreprise
Solution technique de déploiement de CI/CD pour N-applications
La première partie est davantage une nostalgie du bon vieux temps, et la seconde est une expérience que vous pouvez appliquer à vous-même.
C'est comme ça que ça s'est passé historiquement
Année 2015
Nous venions tout juste de commencer à développer des applications mobiles, alors nous ne connaissions rien à l’intégration continue, au DevOps et autres choses à la mode. Chaque mise à jour de l'application était déployée par le développeur lui-même depuis sa machine. Et si pour Android c'était assez simple - assemblé, signé .apk et l'a téléchargé sur la console de développement Google, puis pour iOS, l'outil de distribution via Xcode nous a laissé de belles soirées - les tentatives de téléchargement de l'archive se terminaient souvent par des erreurs et nous devions réessayer. Il s'est avéré que le développeur le plus avancé n'écrit pas de code plusieurs fois par mois, mais publie plutôt l'application.
Année 2016
Nous avons grandi, nous avions déjà réfléchi à la manière de libérer les développeurs d'une journée entière pour une version, et une deuxième application est également apparue, ce qui n'a fait que nous pousser davantage vers l'automatisation. La même année, nous avons installé Jenkins pour la première fois et écrit un tas de scripts effrayants, très similaires à ceux que fastlane montre dans sa documentation.
Malheureusement, jusqu'à présent, seuls nos développeurs savaient comment fonctionnaient ces scripts et pourquoi cette pile infinie de clés était nécessaire, et lorsque quelque chose tombait à nouveau en panne, ils bénéficiaient de «soirées magnifiques» pour analyser les journaux.
Année 2017
Cette année, nous avons appris qu’il existe une voie rapide. Il n’y avait pas autant d’informations qu’aujourd’hui – comment en démarrer un, comment l’utiliser. Et l’outil lui-même était encore rudimentaire à cette époque : des erreurs constantes ne faisaient que nous décevoir et il était difficile de croire à l’automatisation magique qu’elles promettaient.
Cependant, les principaux services publics inclus dans le noyau Fastlane sont gym и pilot, nous avons réussi à le démarrer.
Ils ont été améliorés, ne serait-ce que parce que tous les paramètres nécessaires à leur xcodebuild, vous devez indiquer - gym comprendra indépendamment où et ce qui se trouve. Et pour un réglage plus fin, vous pouvez spécifier les mêmes clés que dans xcodebuild, seule la dénomination des touches est plus claire.
Cette fois, grâce à Gym et au formateur xcpretty intégré, les journaux de construction sont devenus beaucoup plus lisibles. Cela a commencé à gagner du temps sur la réparation des assemblys cassés, et parfois l'équipe de publication pouvait le résoudre par elle-même.
Malheureusement, les mesures de vitesse d'assemblage xcodebuild и gym Nous ne l'avons pas fait, mais nous ferons confiance à la documentation - jusqu'à 30 % d'accélération.
Processus unique pour toutes les demandes
Année 2018 et présent
En 2018, le processus de création et de déploiement d'applications a été entièrement transféré vers Jenkins, les développeurs ont cessé de publier depuis leurs machines et seule l'équipe de publication avait le droit de publier.
Nous souhaitions déjà améliorer le lancement des tests et des analyses statiques, et nos scripts ont grandi et grandi. A grandi et changé avec nos applications. À l’époque, il y avait environ 10 applications, ce qui, étant donné que nous avons deux plateformes, représente une vingtaine de scripts « vivants ».
Chaque fois que nous voulions ajouter une nouvelle étape au script, nous devions copier-coller les éléments dans tous les scripts shell. Nous aurions peut-être pu travailler plus soigneusement, mais souvent de tels changements se terminaient par des fautes de frappe, qui se transformaient en soirées pour l'équipe de publication pour corriger les scripts et découvrir quel type intelligent avait ajouté cette commande et ce qu'elle faisait réellement. En général, on ne peut pas dire que les scripts d'assemblage pour une plate-forme étaient au moins quelque peu similaires. Même s’ils ont certainement fait la même chose.
Afin de démarrer un processus pour une nouvelle application, il était nécessaire de passer une journée à sélectionner une version « fraîche » de ces scripts, à la déboguer et à dire que « oui, cela fonctionne ».
À l’été 2018, nous nous sommes à nouveau tournés vers la voie rapide, encore en développement.
Tâche n° 1 : résumer toutes les étapes du script et les réécrire dans Fastfile
Lorsque nous avons commencé, nos scripts ressemblaient à un chausson composé de toutes les étapes et béquilles dans un seul script shell dans Jenkins. Nous ne sommes pas encore passés au pipeline et à la division par étapes.
Nous avons examiné ce dont nous disposons et identifié 4 étapes qui correspondent à la description de notre CI/CD :
build - installation des dépendances, assemblage de l'archive,
test - exécution de tests unitaires de développeur, calcul de la couverture,
sonar - lance tous les linters et envoie des rapports à SonarQube,
déployer - envoyer un artefact à alpha (TestFlight).
Et si vous n’entrez pas dans les détails, en omettant les clés utilisées dans les actions, vous obtiendrez ce Fastfile :
default_platform(:ios)
platform :ios do
before_all do
unlock
end
desc "Build stage"
lane :build do
match
prepare_build
gym
end
desc "Prepare build stage: carthage and cocoapods"
lane :prepare_build do
pathCartfile = ""
Dir.chdir("..") do
pathCartfile = File.join(Dir.pwd, "/Cartfile")
end
if File.exist?(pathCartfile)
carthage
end
pathPodfile = ""
Dir.chdir("..") do
pathPodfile = File.join(Dir.pwd, "/Podfile")
end
if File.exist?(pathPodfile)
cocoapods
end
end
desc "Test stage"
lane :test do
scan
xcov
end
desc "Sonar stage (after run test!)"
lane :run_sonar do
slather
lizard
swiftlint
sonar
end
desc "Deploy to testflight stage"
lane :deploy do
pilot
end
desc "Unlock keychain"
private_lane :unlock do
pass = ENV['KEYCHAIN_PASSWORD']
unlock_keychain(
password: pass
)
end
end
En fait, notre premier Fastfile s'est avéré monstrueux, compte tenu de certaines des béquilles dont nous avions encore besoin et du nombre de paramètres que nous avons remplacés :
lane :build do
carthage(
command: "update",
use_binaries: false,
platform: "ios",
cache_builds: true)
cocoapods(
clean: true,
podfile: "./Podfile",
use_bundle_exec: false)
gym(
workspace: "MyApp.xcworkspace",
configuration: "Release",
scheme: "MyApp",
clean: true,
output_directory: "/build",
output_name: "my-app.ipa")
end
lane :deploy do
pilot(
username: "[email protected]",
app_identifier: "com.example.app",
dev_portal_team_id: "TEAM_ID_NUMBER_DEV",
team_id: "ITS_TEAM_ID")
end
Dans l'exemple ci-dessus, seule une partie des paramètres que nous devons spécifier : ce sont les paramètres de construction - schéma, configuration, noms de profil de provisionnement, ainsi que les paramètres de distribution - identifiant Apple du compte développeur, mot de passe, identifiant d'application, etc. sur. En première approximation, nous mettons toutes ces clés dans des fichiers spéciaux - Gymfile, Matchfile и Appfile.
Désormais, dans Jenkins, vous pouvez appeler des commandes courtes qui ne brouillent pas la vue et sont facilement lisibles à l'œil nu :
Qu'est-ce que vous obtenez? Des commandes claires pour chaque étape. Scripts nettoyés, soigneusement organisés dans des fichiers fastlane. En nous réjouissant, nous avons couru vers les développeurs pour leur demander d'ajouter tout ce dont ils avaient besoin à leurs référentiels.
Mais nous avons réalisé avec le temps que nous rencontrerions les mêmes difficultés - nous aurions toujours 20 scripts d'assemblage qui, d'une manière ou d'une autre, commenceraient à vivre leur propre vie, il serait plus difficile de les éditer, puisque les scripts seraient déplacés vers des référentiels, et nous n'y avions pas accès. Et, en général, il ne sera pas possible de résoudre notre douleur de cette façon.
Tâche n°2 : obtenir un seul Fastfile pour N applications
Maintenant, il semble que résoudre le problème ne soit pas si difficile - définissez les variables et c'est parti. Oui, en fait, c’est ainsi que le problème a été résolu. Mais au moment où nous avons tout gâché, nous n'avions ni expertise dans Fastlane lui-même, ni dans Ruby, dans lequel Fastlane est écrit, ni d'exemples utiles sur le réseau - tous ceux qui écrivaient sur Fastlane étaient alors limités à un exemple pour une application pour un développeur.
Fastlane peut gérer les variables d'environnement, et nous l'avons déjà essayé en définissant le mot de passe du trousseau :
ENV['KEYCHAIN_PASSWORD']
Après avoir examiné nos scripts, nous avons identifié les parties communes :
#for build, test and deploy
APPLICATION_SCHEME_NAME=appScheme
APPLICATION_PROJECT_NAME=app.xcodeproj
APPLICATION_WORKSPACE_NAME=app.xcworkspace
APPLICATION_NAME=appName
OUTPUT_IPA_NAME=appName.ipa
#app info
APP_BUNDLE_IDENTIFIER=com.example.appName
[email protected]
TEAM_ID=ABCD1234
FASTLANE_ITC_TEAM_ID=123456789
Maintenant, pour commencer à utiliser ces clés dans les fichiers fastlane, nous devions trouver comment les y livrer. Fastlane a une solution pour cela : chargement de variables via dotenv. La documentation indique que s'il est important pour vous de charger des clés à des fins différentes, créez plusieurs fichiers de configuration dans le répertoire fastlane. .env, .env.default, .env.development.
Et puis nous avons décidé d'utiliser cette bibliothèque un peu différemment. Plaçons dans le référentiel des développeurs non pas les scripts fastlane et ses méta informations, mais les clés uniques de cette application dans le fichier .env.appName.
Eux-mêmes Fastfile, Appfile, Matchfile и Gymfile, nous l'avons caché dans un référentiel séparé. Un fichier supplémentaire contenant des clés de mot de passe d'autres services y était caché - .env.
Vous pouvez voir un exemple ici.
Sur CI l'appel n'a pas beaucoup changé, une clé de configuration pour une application spécifique a été ajoutée :
J'ai laissé cette solution pour le moment, bien que Fastlane ait une solution pour télécharger Fastfile via actionimport_from_git, mais cela ne fonctionne que pour Fastfile, mais pas pour les autres fichiers. Si vous voulez « vraiment beau », vous pouvez écrire le vôtre action.
Un ensemble similaire a été réalisé pour les applications Android et ReactNative, les fichiers sont dans le même référentiel, mais dans des branches différentes iOS, android и react_native.
Lorsque l'équipe de publication souhaite ajouter une nouvelle étape, les modifications dans le script sont enregistrées via MR dans git, il n'est plus nécessaire de rechercher les coupables des scripts cassés, et en général, il faut maintenant essayer de le casser.
Maintenant c'est sûr
Auparavant, nous passions du temps à maintenir tous les scripts, à les mettre à jour et à corriger toutes les conséquences des mises à jour. C'était très décevant lorsque les raisons des erreurs et des temps d'arrêt dans les versions étaient de simples fautes de frappe si difficiles à suivre dans le fouillis des scripts shell. Désormais, ces erreurs sont réduites au minimum. Les modifications sont déployées simultanément sur toutes les applications. Et il faut 15 minutes pour insérer une nouvelle application dans le processus - configurez un pipeline de modèles sur CI et ajoutez les clés au référentiel du développeur.
Il semble que l'intérêt de Fastfile pour Android et de la signature de l'application reste inexpliqué ; si l'article est intéressant, j'écrirai une suite. Je serai heureux de voir vos questions ou suggestions « comment résoudriez-vous ce problème » dans les commentaires ou sur Telegram Bachkirova.