Table of contents
Recently, I spent some time for setting up Continuous Integration (CI) and Continuous Delivery (CD) for an enterprise client. I automated build, sign/resign and distribution operations that we have to do for our hybrid mobile applications on a daily basis. No matter what platform you use for building your mobile app, ionic, cordova, nativescript, flutter or react native, they all share common practises and concerns when it comes to the build and distribution phase.
I want to share my experience and hopefully inspire anyone those who are in the process of setting up or maintaining CI/CD. Although it’s a fairly technical article, I’ll also touch business values for luring business owners and managers. So, please bear with me.
Why should you start using continuous delivery pipeline?
You may have too many manual processes and a possible bottleneck on your software deliveries. On daily basis, it can decrease your efficiency on delivering features because of the time you lose and the effort you make on context switching, manual building, fixing the builds and dependency issues, dealing with iOS code signing issues, manual archiving, manual deployment, manual re-packaging, code re-signing, and so on and so forth.
By introducing CI/CD pipeline into your organisation, you can improve the quality of your hybrid mobile apps, accelerate deliveries and automate your processes.
Before going forward, I’d like to go over Continuous Integration, Continuous Delivery, and Continuous Deployment terms. I think it’s important to clarify what they are and how they’re connected. In fact, I’d like to stress what it actually means for your business.
Continuous Integration (CI)
Continuous integration — the practice of frequently integrating one’s new or changed code with the existing code repository — should occur frequently enough that no intervening window remains between commit and build, and such that no errors can arise without developers noticing them and correcting them immediately.
What it could mean for your app and your team
- Assuring code quality by testing unit functions
- Preventing compilation errors
- Code linting
- Early detection of possible issues with external dependencies, such as npm packages and plugins
- Increasing your code coverage
- Faster build times in time
- Guarding a stable, working development version
- Transparency with displaying the results of the builds to everyone
- Deployment automation
Continuous Delivery / Deployment (CD)
Continuous delivery is an extension of continuous integration to make sure that you can release new changes to your customers quickly in a sustainable way. This means that on top of having automated your testing, you also have automated your release process and you can deploy your application at any point of time by clicking on a button.
Continuous deployment is the next step of continuous delivery: Every change that passes the automated tests is deployed to production automatically. Continuous deployment should be the goal of most companies that are not constrained by regulatory or other requirements.
What it could mean for your iOS app and your team
- No more xcode codesigning issues on development and distribution certificates anymore since you don’t need to build on our local computers
- No more context switching for developers to be able to provide a QA build for testers, users, and stakeholders
- No more build errors due to mismatch between system tools and dependencies
- No more waiting times for testers to have a specific build/revision installed on a device
- No more manual release preparation for production with re-building, re-packaging and re-signing with production enterprise certificates
- No more necessity for our customers and stakeholders to stop by the office in order to get a build/version — thanks to beta app distribution
- Any developer or tester is able to trigger a build remotely out of a branch/revision and deploy it for QA or PROD (if you follow continuous delivery approach)
- Any developer or tester is able to trigger a build remotely out of pushing a new code or merging a PR and deploy it for QA or PROD (if you follow continuous deployment approach)
From now on, I’d like to focus on tips and tricks on setting up a CI/CD for your hybrid applications. To avoid complexity, I just refer to ionic app on iOS platform in my examples.
Find bottlenecks and automate manual processes
One of the blockers you might have for setting up your CI environment might be something you have to automate. It can be codesign operation, resign operation, repackaging or a web page that you need to upload a file or submit a form.
Start with analysing your manual processes on your delivery pipeline. Is it a change request you have to submit? Is it a distribution for QA? Is it a resigning operation? Define them and think about the ways to automate them.
Automate with fastlane
Integrate fastlane! Fastlane is a great platform which focuses on solving the problems that existed for years in mobile development environment.
“fastlane handles tedious tasks so you don’t have to” — fastlane.tools
It helps you to organise and maintain your provisioning profiles and certificates for the codesigning, integrates beta deployment and so on.
Automate with your own scripts
For the processes that you can not automate through fastlane or any other helpful platform or library, you may need to write your own scripts.
Always browse npmjs.com before writing your own node.js script
You may require to repackage your application, resign it, upload it to a web page or an enterprise MDM provider. In that case, you should create your own bash executables in order to automate those of your daily operations. Browsing npm packages and building your scripts with node.js might be wise since it’s a large community and there could already be a package for your needs.
“Puppeteer is a Node library which provides a high-level API to control headless Chrome or Chromium over the DevTools Protocol. It can also be configured to use full (non-headless) Chrome or Chromium.”
Puppeteer is a very powerful library and a great toolset if you need to deal with web pages for some of your manual processes. It can be your best friend for automating browser based processes.
I used puppeteer to automate a resigning operation where I had to upload my repackaged application build to a web form and download a resigned one from Nexus servers.
Set up CI configuration
Compiling and building an application package for iOS platform requires an iOS device, xcode, and code signing as we all know. No matter which CI solution you use, you need to identify and point the CI to the right agents for your build configuration.
Make sure that you have build agents with right capabilities for your automated processes
Prerequisites for your build agents
Define your requirements and set prerequisites and capabilities for your CI agent. For instance, let’s say you’re building an ionic app and you have automated some tasks with fastlane and puppeteer. You may need brew, nvm, cordova, xcode, yarn, ionic, ios-deploy, fastlane and google-chrome installed for your agents.
You need to make sure those tools are installed on you CI agent. And as the first step on your build configuration, it’s wise to check if those tools are installed on CI system and if not, just install them with command line scripts!
Assert and install the tools you require for your scripts
Manage developer and enterprise distribution certificates and codesigning on CI agent
If you’re building mobile apps for iOS, you might already know that codesigning is a challenging task. It’s hard to understand and even harder to maintain if you’re working in a large organisation with multiple product teams.
I recommend you to use fastlane match to manage your development certificates for your teams. You should also use match to install your distribution certificates on your CI agent.
You need to introduce a new step in your build configuration to download provisioning profiles and certificates from your certificate repository if you’re using match. Otherwise, you can use sigh & cert to download it right from your Apple developer account. Following code snippet is an example of how you can handle iOS code signing on macOS build agent.
Download your provisioning profiles and certificates, set them to your custom keychain on the CI
I’d like to point to an important detail here. In order to have xcode get your certificates from the keychain during the build, your keychain should be unlocked — see line 7 on the above snippet. Otherwise, your build will be hanging on unlock keychain prompt.
Maintaining your CI scripts
Although you can add command line scripts to your build configuration of your CI, I would advise keeping your build scripts on your source control system. It will be easier to develop, review and maintain your scripts and it will make it possible to see the revision history.
Folder structure example for maintaining your CI scripts
Setting up steps on your build configuration
After building your custom scripts, you need to assign them to your build configuration of steps. Here’s an example of build steps for creating app artifact which is built on Bamboo.
Once you have your artifact (IPA file in our case), you may want to use it for beta deployment. To accomplish that, you can introduce a new stage for deployment and setup your build configuration similar to the one above to deploy the artifact you just built.
Beta app distribution for continuous deployment
Beta app distribution is a very nice way to distribute your app to QA, key users and stakeholders before publishing them to production users. Apple introduces TestFlight for commercial apps which is unfortunately not available for enterprise developer accounts.
If you’re using fastlane, you can get advantage of using prebuilt scripts per beta service — see fastlane beta. It has built-in actions for TestFlight, Fabric Beta, HockeyApp and TestFairy. Otherwise, you can also easily communicate with their APIs to upload your package and distribute it.
Distribution flow of beta app builds
You can setup an automated distribution stage on your CI as an additional step on your builds or use deployment pipeline of your CI.
Down below, you see a simple bash script which uploads your app artifacts to HockeyApp. HockeyApp automatically distributes this deployment to selected user group and sends email/slack notifications accordingly with your app’s installation link in it.
In case of you don’t use fastlane, it’s not that complicated to write your own beta app deployment script
In a nutshell
Although this is a longer article than I planned, it’s still an overview of the whole pipeline with some in-depth topics such as code signing, CI configuration and automating processes.
I hope it helps you to automate your processes and enable CI/CD for your organisation if it’s not there yet. Otherwise, you might feel the emotional cycle of manual delivery.
We all fell down the cliff of urgency. I feel you.
Please leave comments if you have any questions or remarks! I’d be glad to hear your experience on your journey. Don’t forget to like and follow if you find my article valuable. Cheers!