Fastlane & Travis CI

Fastlane is a command-line tool used to automate a lot of tasks (building projects, running tests, distributing builds) with the help of a suite of sub-tools.

Travis CI is a continuous integration service used to build and test software projects hosted at GitHub. For every pull request in our repos, Travis will locally make the proposed merge, then use Fastlane to build the project and run its tests, then uploads test coverage details to CVR. When a pull request is merged, Travis can also send builds to HockeyApp or iTunes Connect automatically (again, with the help of Fastlane).

This document includes instructions for configuring both on new projects. If you're adding this functionality to an existing project, see the Switching to fastlane section at the bottom for some details.

Prerequisites

There are some things you'll need before we get started.

  1. Ask a senior engineer for help with a couple things:
  1. Ask the client to add you to their Apple Developer Account as an Admin.
  1. Run bundle install in the root of your repo. This will install fastlane and related gems.

  2. Commit Gemfile.lock if it was changed by bundler.

  3. If you don't already have the travis gem installed, do so now by running sudo gem install travis.

Fastlane Configuration

All Fastlane config files are in the fastlane directory.

  1. Review the Fastfile. This contains the "lanes" used by Fastlane to actually perform various build tasks.
  1. Review the Appfile. This file provides details about the app as it exists in the Apple ecosystem.
  1. Review the Matchfile. This file provides configuration for match, which is the Fastlane tool responsible for managing signing certificates.
  1. Review the local_config.sh. This file sets environment variables that normally contain passwords and access keys. When Fastlane is run on Travis, these values come from encrypted values in .travis.yml (we'll do that in a later step).
  1. Try running a lane to confirm the basic configuration is correct. When running Fastlane locally, be sure to load the contents of local_config.sh first, using the . command, to set environment variables. You must also use bundle exec to ensure that the correct version of fastlane and other tools (specified in the Gemfile) are used:

    . ./fastlane/local_config.sh
    bundle exec fastlane ios test
  2. Setup the signing certificates and provisioning profiles for the app by running the following match commands. You may be prompted for the password used to encrypt the certificates repo and your Apple account password, if they're not already in your keychain.

    bundle exec fastlane match appstore
    bundle exec fastlane match adhoc
    bundle exec fastlane match development
  3. Once the certs and profiles have been generated, go into the Xcode general build settings tab for the main target. Then select the appropriate "Signing (Debug)" and "Signing (Release)" provisioning profile dropdown values and commit.

That should do it!

Travis Setup

  1. Review the contents of .travis.yml:
  1. Paste the encrypted S3 credentials from the senior engineer (from the Prerequisites section) into the addons section at the bottom of .travis.yml.

  2. Generate a Personal Access Token with repo scope on GitHub. This will be used to authenticate with Travis.

  3. Log in to the travis command line tool. Run travis login --pro --github-token [token], replacing [token] with the one you generated in the previous step.

  4. Encrypt the "secure" properties in the Secure environment variables section of the .travis.yml file. For each variable in that section, run the travis encrypt command from the root of your repo:

    travis encrypt 'VARIABLE_NAME=TheValueToEncrypt' -r vokal/YourRepoName

Replace VARIABLE_NAME with the name of the variable to set, TheValueToEncrypt with the value to assign to the variable, and YourRepoName with the name of your repo. This will print out a line like this:

```yaml
  secure: "MUMOHFGS1M23fGy3crZ5/RIINdmFetHRnnLvrUsPhkJ3/J4acPRM+9TyLaJImmInOo4sz4Y9/p38a7Xvp0GP0RV7wLqhtdsawKXPd1wmD6IIkx8PCvhA2HH1O3PxcKs8NYH5SQWflSperQ+s+LMV4ePFbPBkO3JpKtsKP/gllYk="
```

Copy this output, and use it to replace the line in .travis.yml where the variable had previously been set to FIXME. Make sure it's still prefixed with a -, and that the variable you encrypted is the one mentioned in the comment above the spot where you paste it.

A few notes on secure variables:

Distribution Channels

Fastlane is used to upload builds to Hockey and/or iTunes Connect (for TestFlight and App Store). This can be done locally from your machine, but we typically have Travis do so on merge builds (which happen when a pull request is merged) so that builds are automatically available in HockeyApp to be sent out to product owners and other testers.

Note that the distribute.sh script (which is run by Travis on merge builds) bails out if either HOCKEY_API_TOKEN or ITC_PASSWORD is still set to "FIXME". If you only want to have builds automatically uploaded to one of these services, make sure you comment out the other in .travis.yml.

Signing

All builds must be signed using a Distribution certificate and the appropriate provisioning profile so that they may be installed by non-developers.

Fastlane's sigh and match utilities facilitate signing by using provided credentials to log in to the Apple Developer Center and grab provisioning profiles and certificates, respectively, for signing your builds.

Most of this is automated. You only have to set one variable, if you haven't already:

  1. Ask the director to encrypt the Apple ID password for build@vokal.io as a secure variable called FASTLANE_PASSWORD, using the process described previously, and drop it into your .travis.yml.

Lanes for distributing via HockeyApp and iTunes Connect will provide the necessary information to the archive_build private lane, which calls gym to build and sign an .ipa.

HockeyApp

To upload to HockeyApp, you need to generate an upload token.

  1. Go to Account Settings, select API Tokens in the left sidebar, and generate a new Upload Only token for your app.

  2. Add this token to your local_config.sh as HOCKEY_API_TOKEN, then encrypt it as a secure environment variable with the same name in .travis.yml.

Once this variable is added, Fastlane will be able to run the hockey_staging and hockey_prod lanes, uploading staging or production builds to HockeyApp.

If you get an SSL error locally when deploying to HockeyApp, see the fastlane FAQs.

iTunes Connect

  1. Invite build@vokal.io to iTunes Connect as a Developer.

  2. Have a senior engineer encrypt the password as ITC_PASSWORD for your .travis.yml.

  3. Add build@vokal.io as the ITC_USERNAME in your .travis.yml. This one doesn't need to be encrypted.

  4. If you'd like to upload builds to iTunes Connect from your machine, put your own account credentials in local_config.sh as ITC_USERNAME and ITC_PASSWORD. Once you do, you can upload builds by running:

    . ./fastlane/local_config.sh
    bundle exec fastlane ios itc

NOTE: Steps 1-3 are only needed if you want to automatically upload builds to iTunes Connect after every successful Travis merge build. If you only want to manually upload builds to iTunes Connect from your machine on an on-demand basis using Fastlane, then only step 4 is needed.

NOTE: Once a build is uploaded to iTunes Connect, it cannot be deleted, and it also cannot have a build with a lower short version number uploaded. Be accordingly careful when testing this functionality.

Build Wall and Drone

The build walls around the office are based on statuses from Drone, which is the build server that's used by other engineering disciplines. Since our builds run on Travis, we have sort of a bridge build that also runs on Drone and waits for a notification from Travis that the build has finished, so that it can be displayed on our build walls.

To show the Travis build status on our build walls, activate the repo from the repo list on our Drone server (a senior dev can grant you access if you need it). If you created the project from our project template, that's all you need to do.

If you created a project from scratch, or inherited one that wasn't created from our template, you just need to make two more adjustments to your project.

  1. Add a .drone.yml file at the root, with the contents of the file in the project template.
  2. Add a notifications section to your .travis.yml, again matching the contents of the file from the project template.

Switching to fastlane

We started using fastlane in early 2016, and projects before that mostly used custom scripts for Travis. If you're updating one of those projects to use fastlane, it's probably best to just start from scratch: our build flow has evolved a lot since adopting fastlane (and some variable names changed, like HOCKEY_API_TOKEN), so attempting to update the existing Travis config in the project is likely to be a pain. Just replace it and move on.

Start by copying some things from our Xcode project template to make sure you've got the latest scripts and templates for config files. From the base template directory, you'll need:

There are some changes you might need to make to the project itself:

  1. Remove the ad-hoc configuration and scheme
  2. Set the provisioning profiles to Automatic in the build settings, for all configurations
  3. Change your main scheme to use the Release configuration for the Archive action
    • Main scheme should test both UI and Unit test targets
  4. Update your .gitignore to include everything listed in the project template version
  5. Review your Build Phases and replace Run Script phases with calls to scripts in the Scripts directory, where appropriate
  6. Make use of the USE_PRODUCTION_SERVER user-defined build setting, to toggle between staging and production API servers. This includes multiple steps. The easiest way to add this is to create a new project using our template and include the starter network utility. Then, search this dummy project for USE_PRODUCTION_SERVER to see how the flag should be used.

Finally, go back to the top of this document and follow the instructions.