Building Quality iOS Apps, Quickly
iOS MacAt Big Nerd Ranch, we take pride in building quality apps for our clients. Unfortunately, quality isn't the only concern when building an app...
In Part 1, we set up two Fastlane commands:
bump
to increment the build number andsubmit_to_testflight
to upload the build to our TestFlight groupLet’s configure CircleCI to run these commands for us when new features are delivered to our master branch.
Let’s tell Circle CI that we want it to run some projects for us. Click on CircleCI’s Add Projects tab. Find your repository in the list and click Set Up Project
. Follow the initial setup steps on that page and then click Start Building
.
In config.yaml
, add a new job to your job list:
bump-build: macos: xcode: "10.2.0" environment: # Silences warning from Fastlane - LC_ALL: "en_US.UTF-8" - LANG: "en_US.UTF-8" steps: - checkout # Install fastlane and its dependencies - run: name: install Brewfile command: brew bundle - run: name: Installing gem dependencies command: bundle install # Securely connect to GitHub - add_ssh_keys: fingerprints: - "SO:ME:FI:NG:ER:PR:IN:T" # Call the bump lane - run: name: Bump the build number and commit command: bundle exec fastlane bump
The interesting part is add_ssh_keys
. Deployment keys let CircleCI access your code. However, while you can set a service deployment key in CircleCI, it only gives read access. The fastlane bump
command needs write access to push the version bump commit to master. Therefore, we need to generate and register a user-deploy key with write access by following these instructions. Paste the key’s fingerprint here.
Notably:
Let’s add the job for submitting to TestFlight:
submit_to_testflight: macos: xcode: "10.2.0" environment: # Silences warning from Fastlane - LC_ALL: "en_US.UTF-8" - LANG: "en_US.UTF-8" steps: - checkout # Install fastlane and its dependencies - run: name: install Brewfile command: brew bundle - run: name: Installing gem dependencies command: bundle install # Securely connect to GitHub - add_ssh_keys: fingerprints: - "SO:ME:FI:NG:ER:PR:IN:T" # Call the submit lane - run: name: Deploy new build to TestFlight command: bundle exec fastlane submit_to_testflight
This looks very similar to the step for making the build. In fact, the only differences are:
fastlane submit_to_testflight
This SSH key is the one Circle CI will use to download your credentials from the repo that fastlane match
uses to store them. If you attempt to reuse your key from earlier, GitHub will reject it. Instead, you’ll need to do the same key generation process again, and add the fingerprint for the SSH key associated with the credentials repo here.
Now that we’ve got two jobs, let’s put them together into a workflow:
#Defines work-flows for the jobs specified above workflows: version: 2 build-test-lint: jobs: - build-and-test: filters: tags: only: /.*/ - bump-build: requires: - build-and-test filters: branches: only: master tags: only: /.*/ - deploy-beta: requires: - build-and-test filters: branches: ignore: /.*/ tags: only: /^builds.*/
That’s a lot. Let’s look at each job in that workflow individually.
- build-and-test: filters: tags: only: /.*/
This builds and tests any commit to any branch. See CircleCI’s excellent guide on how to configure automated tests.
The filter here is odd. Why would we filter to a regex that matches everything? This is how CircleCI knows it should trigger this workflow for either a tag match or a branch match. It looks superfluous right now, but adding the “only run it for every tag” filter means we can specify “only run it for specific tags” in later, dependent jobs.
- bump-build: requires: - build-and-test filters: branches: only: master tags: only: /.*/
This runs our fastlane bump
job. This will only run on the master branch, and will run with any specified tag. And, it’ll only run after build-and-test
successfully completes.
Just like before, the “filter to only all of the tags” looks superfluous, but it’s not. Now that our parent task has started filtering for tags, if any job doesn’t specify a tag filter, then all tag filters will be ignored.
And now, the grand finale of CI config:
- deploy-to-testflight: requires: - build-and-test filters: branches: ignore: /.*/ tags: only: /^builds.*/
Finally, our deploy task ignores branches and only triggers if it sees a tag that starts with builds
. You can probably make the tag regex more specific, but this is good enough for me.
Both of these
filters
values are OR’d together. If we specifiedbranches: only: master
with this filter tag, then it would run for every commit on master and also any commits that start withbuilds
. Ignoring the branch entirely and havingbuilds
tags only added to master is the only way to achieve the desired effect.
Your automated process should now look like this:
You’re still not done! There’s some state on your local machine that you need to go into CircleCI and add as environment variables. Specifically:
MATCH_PASSWORD
– This is the password you use to decrypt your fastlane credentials.FASTLANE_PASSWORD
– This is the Apple ID password of the account you use to submit builds to Apple.If the shared build account follows fastlane’s recommendation and doesn’t have two-factor authentication enabled, then you’re done. Otherwise, you’ll need these additional environment variables:
FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD
– This can be generated in Apple ID Settings, underneath Security > Generate Password.FASTLANE_SESSION
– A session token that’s sufficent for two-factor authentication. To generate, type the following command in the terminal, using the build account’s email address: fastlane spaceauth -u user@email.com
The
FASTLANE_SESSION
expires after a month. You will need to update this environment variable monthly in order to keep the build process automatic. Unfortunately, that’s the best fastlane can do.
That’s it! Make your commits, get them reviewed and merged to master, and about 20-30 minutes later you should get a notification that you’ve got a new build to download from TestFlight.
If you’re anxiously watching the workflow process as this goes on, you should see each of the five jobs:
build-and-test
.bump-build
and tag the commit.build-and-test
bump-build
with no effect on the tag commit.deploy-to-testflight
.At Big Nerd Ranch, we take pride in building quality apps for our clients. Unfortunately, quality isn't the only concern when building an app...
How can you detect when the user connects their phone to their car’s stereo? This simple question that came up during a feature brainstorm...
Automate your build and deploy process with fastlane and CircleCI! In this first part, we'll describe our current process and illustrate how we can...