iOS Deployment Pipeline with Travis Stages

The process of Continuous Integration performs various activities like analysing, building, testing and deploying iOS apps. It would be a great idea to break down each build tasks into various stages and execute them independently. This process is also called Build Pipeline Or Deployment Pipeline. As an iOS developer, you might have experienced that building an iOS app can take a lot of time so as testing. The pipeline is the way to deal with each stage of iOS development to get fast feedback. We probably don’t want to get build failure for code styling issue after spending hours of build and test phase. The self-hosted Continuous Integration Servers like Jenkins and  TeamCity has good support to create build pipelines but cloud-based CI servers like TravisCI, CircleCI and some others are also rolling out deployment pipelining features. In this post, we will see how to setup iOS deployment pipeline using Travis Stages feature. Please note, I have used TravisCI as an example because I used it for some of my open-source projects. There might be similar features available for other could based CI servers as well.

Stages of iOS Deployment

Before jumping into  TravisCI setup, we will see what are the important stages of deploying any iOS apps. The major build phases are

  • Analysing Source Code for Code Styling Issues
  • Testing with XCTest or Other Frameworks
  • Building and Archiving iOS app
  • Distributing an iOS app to different beta testing services
  • Uploading iOS app to iTunes Connect

These are the major stages that have to be automated on continuous integration server to enable automatic deployments.

Travis Stages

Just in case if are new to TravisCI, It is a cloud-based Continuous Integration platform embedded with Github which allow running CI builds for the open-source as well as an enterprise project. It has good documentation to get started with Continuous Integration. TravisCI has announced new feature Travis Stages to enable the deployment pipelines for open-source as well as enterprise projects. The stages can be enabled by adding following code sample in the .travis.yml file

In order to apply this principle in the iOS projects, let’s create an  open-source project on GitHub with following (you can use any iOS app)

  • Create Blank single view app named SwiftLint-CI with Unit and UI Test Targets in the Xcode
  • Add SwiftLint using CocoaPods for checking Swift Code Syntax. This can be done creating Podfile and running pod install  command.

Now that, we have a basic iOS project to be configured for CI. We can now add support to run the build on TravisCI and enable following stages.

  • Build Stage to Lint Swift code with SwiftLint
  • Build Stage to run unit tests
  • Build Stages to run UI tests

Creating .travis.yml with Stages

TravisCI uses macOS virtual images to run builds, the list of the all the images can be found here. We can pick latest xcode9  images to run a build for our demo app. We have to run a script to execute SwiftLint and run XCTest using Fastlane Scan. We can setup our .travis.yml  file like this:

The config file above will run 3 different stages for SwiftLint, unit testing and UI testing respectively. Once build is triggered on TravisCI, it will look like this

This indicates that we have build pipeline for each stage and no stage will run unless the previous stage is passed.

Extending Travis Stages for iOS Deployment

Now that, we have setup up build pipeline for code analysis and running unit and UI tests. We can take this pipeline further to deploy an iOS app to iTunes Connects. Automating and distributing builds are not in the scope of this post but you can read my previous post on automating iOS deployments to iTunes connects using Fastlane tools  here. We can extend Travis stages to deploy an app like this:

This configuration will take our iOS app to the TestFlight assuming we setup all the provisioning and certificates in the TravisCI virtual machines. Note that you have to use different Fastlane  actions to create keychain, import certificates to the keychain to allow TravisCI virtual machine codesign an app. In this way, we can break down iOS deployment phases into TravisCI stages for better visibility.

Parallelising Travis Build within Stages

We can still parallelise Travis builds within stages to speed up the overall build execution. We can run unit and UI tests in parallel as well we can distribute an IPA to multiple platforms like Fabric and TestFlight at the same time. Not sure TravisCI has documented the parallelism but there is a trick to run the builds in the parallel in the stage, we have to give the same name to the stage to run in the parallel. In our SwiftLint-CI app, we can parallelise running unit test as well as UI tests by calling it as ‘XCTest’ stage something like this :

Note that, we have given the same name to the build stage but running different scripts for each stage. This will run “XCTest” stage in the parallel. That’s a trick to run Travis builds in parallel within a stage. The parallel build will look like this:

 

Pros and Cons of using Travis Stages

Although the Travis build stages seems to be the great options to create deployment pipelines, there are some pitfalls we need to consider. Here are some pros and cons of using Travis build stages for iOS deployment pipelines.

Pros

  • We can have visibility of builds for each stage of deployment pipeline
  • We can get early feedback if build stage fails within deployment pipeline
  • Can apply parallelism within build stage as we can run multiple jobs in parallel on the stage. Currently, we running unit tests and UI tests in parallel.
  • Assign environment variable per stage
  • Can be used for deploying app to Fabric and TestFlight using different stages

Cons

  • Still in Beta and has some bugs. Check known issues here
  • Trigger new VM for every build in the stage so check out the repo for each task is time-consuming
  • Need to run the stage with the same name to achieve parallelism which is a duplication of script execution.
  • Can not share data between stages, need to use AWS S3 bucket which isn’t feasible.

Source Code & TravisCI Builds

  • GitHub Source Code 

The sample Source Code for this post is available on Github repository SwiftLint-CI

  • TravisCI builds

Sequential build is available here and parallelized build is here

Conclusion

The cloud-based CI servers are providing an ability to run iOS builds in multiple stages to create seamless deployment pipelines for iOS apps. We can take advantage of such features for better feedback and visibility in the build process.