Lately, I had to set up a continuous integration (CI) pipeline for multiple versions of an iOS and tvOS app. Since I didn’t find a lot of information on how to do this in a simple way I decided to write this blog post.
Guest post by Tiago Martinho, software entrepreneur. The original post appeared on Medium.
Tiago is a Portuguese Software entrepreneur currently working with ThoughtWorks in Barcelona. He hosts a Swift Peer lab every Saturday and loves to build mobile applications. Currently, he is trying to bootstrap a podcast about iOS and Swift with his friend Lewis.
Use Case
This post is useful if you have:
- A White Label Application (WLA) that contains multiple variations of the same application;
- An application that targets multiple platforms (iOS/tvOS/macOS);
And you don’t want to have duplication in your CI pipeline or have to define your environment variables in the pipeline.
In my case I have two versions (lite and premium) of a universal app (iOS and tvOS) so in total four variations.
Tools
I used the Fastlane tool to automate the tasks needed to deploy the app.
Like all tools, it has advantages and disadvantages.
Advantages:
- Your pipeline is not tied to any particular service;
- It can be run locally, in a service or in a remote machine;
- It depends on an open-source project;
Disadvantages:
- You need time to configure it;
- You need time to maintain it;
If you are not familiar with Fastlane please refer to their documentation.
Fastlane Configuration
Reading the documentation of fastlane the use of environment variables seemed the best fit for my use case.
In order to load different variables for each variation of the app, you need to define a file for each variation.
In my case I defined 4 files with the following names:
- .env.ios
- .env.iosfree
- .env.tvos
- .env.tvosfree
Each file contains the variables needed to build that specific version of the application:
For tvOS the platform is:
PLATFORM=appletvos
These variables are loaded by adding the option env when invoking fastlane:
The pipeline reads these variables and is defined in the Fastfile:
This pipeline is doing the following five steps:
- cocoapods: installing all the project dependencies with Cocoapods
- run_tests: running the tests that verify our app works correctly
- increment_build_number: incrementing the build number since iTunes Connect requires an ever incrementing build number
- build_app: building our application
- upload_to_app_store: deploying our application to iTunes Connect
Continuous Integration
Fastlane integrates effortlessly into existing CI services
I used Bitrise, but you could also use CircleCI, Travis CI, or Jenkins.
After following the guided setup from Bitrise when adding a new app you end up with all the configuration needed (Webhook, Setup of Workflow, etc.)
After this, you need to remove all the steps you don’t need. In my case, the pipeline is very simple and after cloning the project and installing the certificates it calls the appropriate Fastlane lane ‘release’:

Bitrise Pipeline
It’s also needed to setup the Secrets to build the app (FASTLANE_USER, FASTLANE_APPLE_ID, FASTLANE_PASSWORD) and verify the correct stack is selected in my case is Xcode 9.3.x on macOS 10.13.
If you also want to use Bitrise and this post was helpful please use my referral link so I can win a Bitrise t-shirt 😄.
Conclusion
In this blog post we saw how to automate the deploy of multiple versions of the same application for different platforms, iOS and tvOS, using Fastlane and Bitrise.