Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

iOS Deployment Pipeline With Travis Stages

DZone's Guide to

iOS Deployment Pipeline With Travis Stages

Learn how to create a pipeline for continuous integration in development of your iOS app with Travis Stages, from the TravisCI cloud-based server.

· Mobile Zone
Free Resource

Download this comprehensive Mobile Testing Reference Guide to help prioritize which mobile devices and OSs to test against, brought to you in partnership with Sauce Labs.

The process of Continuous Integration performs various activities like analyzing, building, testing, and deploying iOS apps. It would be a great idea to break down each build task 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, as can 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 a build failure for code styling issues after spending hours in the build and test phase. Self-hosted Continuous Integration servers like Jenkins and TeamCity have 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 the important stages of deploying any iOS apps. The major build phases are

  • Analyzing 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, and
  • Uploading the iOS app to iTunes Connect.

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

Travis Stages

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

jobs:
  include:
    - stage: test
      script: ./test 1
    - # stage name not required, will continue to use `test`
      script: ./test 2
    - stage: deploy
      script: ./deploy

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

  • Create a blank single view app named SwiftLint-CI with Unit and UI Test Targets in Xcode.
  • Add SwiftLint using CocoaPods for checking the Swift code syntax. This can be done by creating a Podfile and running the 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 the 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 set up our travis.yml file like this:

language: objective-c
osx_image: xcode9
notifications:
  email: false
branches:
  only:
    - master

before_install:
  - gem install fastlane --no-ri --no-rdoc --no-document

jobs:
  include:
    - stage: Swiflint
      script:
        - ./Pods/SwiftLint/swiftlint --reporter junit

    - stage: XCTest
      script:
        - fastlane scan -s SwiftLint-CITests

    - stage: XCUITest
      script:
        - fastlane scan -s SwiftLint-CIUITests

The config file above will run three 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 a 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:

jobs:
  include:
    - stage: Swiflint
      script:
        - ./Pods/SwiftLint/swiftlint --reporter junit

    - stage: XCTest
      script:
        - fastlane scan -s SwiftLint-CITests

    - stage: XCUITest
      script:
        - fastlane scan -s SwiftLint-CIUITests

    - stage: Build App 
      # Write a script to Create keychain, Import certificate, Download provisioning profies in the TravisVM before build 
      script: 
        - fastlane gym -s SwiftLint-CI -q Release 

    - stage: Upload To TestFlight 
      script: 
        - fastlane pilot upload --changelog "New Features"

This configuration will take our iOS app to the TestFlight assuming we set up 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.

Parallelizing Travis Builds Within Stages

We can still parallelize 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 parallel in the stage; we have to give the same name to the stage to run in parallel. In our SwiftLint-CI app, we can parallelize running unit tests as well as UI tests by calling it the "XCTest" stage, something like this:

jobs:
  include:
    - stage: Swiflint
      script:
        - ./Pods/SwiftLint/swiftlint --reporter junit

    - stage: XCTest
      script:
        - fastlane scan -s SwiftLint-CITests

    - stage: XCTest
      script:
        - fastlane scan -s SwiftLint-CIUITests

Note that we have given the same name to the build stage but are running different scripts for each stage. This will run the "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 seem to be 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 the deployment pipeline.
  • We can get early feedback if a build stage fails within the deployment pipeline.
  • We can apply parallelism within a build stage as we can run multiple jobs in parallel in the stage. Currently, we are running unit tests and UI tests in parallel.
  • We can assign environment variablea per stage.
  • Travis can be used for deploying apps to Fabric and TestFlight using different stages.

Cons

  • Still in Beta and has some bugs. Check known issues here.
  • Triggers a new VM for every build in the stage, so checking out the repo for each task is time-consuming.
  • We need to run the stage with the same name to achieve parallelism, which is a duplication of script execution.
  • We can not share data between stages; we 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: The sequential build is available here and the parallelized build is here.

Conclusion

The cloud-based CI servers are providing the 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.

Analysts agree that a mix of emulators/simulators and real devices are necessary to optimize your mobile app testing - learn more in this white paper, brought to you in partnership with Sauce Labs.

Topics:
swift ,devops ,continuous delivery ,continuous integration ,deployment ,ios ,travisci ,mobile ,mobile app development

Published at DZone with permission of Shashikant Jagtap, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}