ProHoster > Blog > Administration > Mobile CICD experience: one fastlane standard for many mobile applications
Mobile CICD experience: one fastlane standard for many mobile applications
I'd like to talk about continuous integration and mobile app delivery with fastlane. How do we implement CI/CD on all mobile applications, how did we go about it and what happened as a result.
The network already has enough material on the tool, which we lacked so much at the start, so I will deliberately not describe the tool in detail, but will only refer to what we had then:
The background of the emergence of mobile CI / CD in the company
Technical solution for rolling out CI/CD to N-applications
The first part is more nostalgia for the old days, and the second is an experience that you can apply at home.
That's how it happened historically
Year 2015
We just started developing mobile applications, then we still didn’t know anything about continuous integration, about DevOps and other trendy things. Each update of the application was rolled out by the developer himself from his machine. And if for Android it's easy enough - collected, signed .apk and threw it into the Google Developer Console, then for iOS, the then distribution tool through Xcode left us gorgeous evenings - attempts to download the archive often ended in errors and had to be tried again. It turned out that the most pumped developer several times a month does not write code, but is engaged in the release of the application.
Year 2016
We grew up, there were already thoughts on how to free developers from a whole day for the release, and a second application appeared, which only pushed us more towards automation. In the same year, we first installed Jenkins and wrote a bunch of ugly scripts, very similar to those that fastlane shows in their documentation.
Unfortunately, only our developers knew about how these scripts work and why this endless bundle of keys was needed, and when something broke again, they got “splendid evenings” for parsing the logs.
Year 2017
This year we learned that there is such a thing as fastlane. There was not as much information as it is now - how to start, how to use. Yes, and the tool itself was still damp then: constant errors only disappointed us, and it was hard to believe in the magical automation that they promised.
However, the main utilities included in the fastlane core are − gym и pilot, we managed to start.
Ennobled, if only because not all the parameters necessary for xcodebuild, you need to specify - gym will independently understand where and what lies. And for finer tuning, you can specify the same keys as in xcodebuild, only the naming of the keys is clearer.
This time, thanks to gym and the built-in xcpretty formatter, the build logs are much more legible. This began to save time on fixing broken builds, and sometimes the release team could figure it out on their own.
Unfortunately, measurements on assembly speed xcodebuild и gym we did not, but we will believe the documentation - up to 30% acceleration.
One process for all applications
Year 2018 and present
By 2018, the process of building and rolling out applications completely moved to Jenkins, the developers stopped releasing from their machines, only the release team had the right to release.
We already wanted to tighten up the launch of tests and static analysis, and our scripts grew and grew. Grow and change along with our applications. At that time, there were about 10 applications. Given that we have two platforms, this is about 20 “living” scripts.
Every time we wanted to add a new step to a script, we had to copy-paste the pieces into all shell scripts. Perhaps it was possible to work more carefully, but often such changes ended in typos, which already turned into evenings of release teams to fix scripts and find out which of the smart people added this command and what it actually does. In general, it cannot be said that the scripts for building for one platform were at least somewhat similar. Although they certainly did the same thing.
In order to start a process for a new application, it was necessary to spend a day to pick up a “fresh” version of these scripts, debug it and say that “yes, it works”.
In the summer of 2018, we once again looked towards the still developing fastlane.
Task #1: Summarize all script steps and rewrite them in Fastfile
When we started, our scripts looked like a footcloth of all the steps and crutches in one shell script in Jenkins. We have not switched to pipeline and division by stage yet.
We looked at what we have and identified 4 steps that fit the description of our CI / CD:
build - install dependencies, build archive,
test - launching developer unit tests, calculating coverage,
sonar - launch all linters and send reports to SonarQube,
deploy - sending an artifact to alpha (TestFlight).
And if you don’t go into details, omit the keys used for actions, you get this 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
In fact, our first Fastfile turned out to be monstrous, considering some crutches that we still needed, and the number of parameters that we substituted:
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
In the example above, only part of the parameters that we need to specify: these are the build parameters - scheme, configuration, Provision Profile names, as well as distribution parameters - Apple ID of the developer account, password, application ID, and so on. As a first approximation, we put all these keys in special files - Gymfile, Matchfile и Appfile.
Now in Jenkins you can call short commands that do not “blur” your eyes and are well read by the eye:
What did you get? Clear commands for each step. Well-groomed scripts neatly organized into fastlane files. Rejoiced, we ran to the developers with a request to add everything we needed to our repositories.
But we realized in time that we would face the same difficulties - we would still have 20 build scripts that would somehow begin to live their lives, it would be more difficult to edit them, since the scripts would move to the repositories, and we don’t have access there. And, in general, to solve our pain in this way will not work.
Task #2: get a single Fastfile for N-applications
Now it seems that solving the problem is not so difficult - set the variables, and let's go. Yes, that is how the problem was solved. But at the moment when we screwed it up, we had neither expertise in fastlane itself, nor in Ruby, in which fastlane is written, nor useful examples on the network - everyone who wrote about fastlane then was limited to an example for one application for one developer.
Fastlane knows about environment variables, and we have already tried this by setting the password from the Keychain:
ENV['KEYCHAIN_PASSWORD']
Looking at our scripts, we've highlighted the common parts:
#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
Now, in order to start using these keys in fastlane's files, it was necessary to figure out how to deliver them there. Fastlane has a solution for this: loading variables via dotenv. The documentation says that if it is important for you to load keys for different purposes, spawn several configuration files in the fastlane directory .env, .env.default, .env.development.
And then we decided to use this library a little differently. Let's put in the developers' repository not the fastlane scripts and its meta information, but the unique keys of this application in the file .env.appName.
Sami Fastfile, Appfile, Matchfile и Gymfile, we hid in a separate repository. An additional file with password keys from other services was also hidden there - .env.
An example can be seen here.
On CI, the call has not changed much, a configuration key for a specific application has been added:
Left this solution for now although Fastlane has a solution to download Fastfile via actionimport_from_git, but it only works for Fastfile, it doesn't work for other files. If you want “just really beautiful”, you can write your own action.
A similar set was made for Android applications and ReactNative, the files are in the same repository, but in different branches iOS, android и react_native.
When the release team wants to add some new step, the changes in the script are fixed via MR in git, there is no more need to look for the culprits of broken scripts, and in general - to break it now, you have to try.
Now it's all right
We used to spend time maintaining all the scripts, updating them and fixing all the consequences of updates. It was very frustrating when the causes of errors and release downtime were simple typos that are so hard to keep track of in a hodgepodge of shell script. Now such errors are reduced to a minimum. Changes are rolled immediately to all applications. And it takes 15 minutes to start a new application into the process - set up a template pipeline on CI and add keys to the developer's repository.
It seems that the item with Fastfile for Android and the signature of applications remained unlit, if the article is interesting, I will write a sequel. I will be glad to your questions or suggestions “how would you solve this problem” in the comments or in Telegram bashkirova.