Mobile Automation: What is fastlane?

Rick Owers
Remote iOS Dev
Published in
11 min readMar 6, 2020

How many automated tasks do you have in your mobile development process?

If your answer is a few, or even 0, I hope to show you the power that automation can bring to your development process. Leveraging an open source tool called fastlane, I will show you how you can save yourself and your team hours of development time.

Why Focus on Automation?

Automating workflows can work for indie developers, small startups, and large companies alike. Here are some reasons to bring automation into your development process.

Cost Savings

Mobile development is expensive. In my experience, the average hourly cost of an iOS developer is roughly $50–70. For contractors or freelancers, that can easily push over $100+/hour. By automating tasks, you can remove hours of manual workflow and allow developers to do what they do best: code.

Reduce Tedious Tasks

Developers take pride in their code and the results of their efforts. They do not take pride in managing Provisioning Profiles, Certificates or the manual process of releasing an Ad-hoc or production build. Tedious tasks such as these can easily be managed and automated.

Increase an App’s Stability

An application’s stability should be a top concern for a developer and an organization. The crash rate, unit test coverage, and overall performance of an application should be assessed as much as possible and at every step of the development processes. Having automated tasks that can run linting rules, unit tests, ui tests, performance tests, and build processes at regular intervals will ensure your code evolves with fewer regression issues and a higher degree of overall stability.

Attracts Future Talent

Great developers desire great teams with great processes. The more robust your automated processes are, the more likely you will attract talented developers.

Place yourself in the shoes of a developer applying for a new job. If a company cares about code quality (unit tests and linting), focuses on code coverage (testing), and has a sophisticated CICD pipeline (automation), you are more likely to get excited about the company and the position.

What is fastlane?

The tagline on the fastlane website says it all:

The easiest way to build and release mobile apps.
fastlane handles tedious tasks so you don’t have to.

With over 400 different integrations, you can really automate all the tedious tasks away and focus on developing new code.

Fastlane is an open source tool that is distributed under the MIT license. It is an automation software tool that can be run locally on your development machine or remotely on a service like Bitrise, circleci, or a jenkins server.

The following four tasks will quickly get you setup with fastlane as well as let you see the true power fastlane can provide your development process.

Step 1: Installing fastlane

By installing a CLI (command line interface) tool via a couple simple commands in your terminal, you will have the full power of all automation at your finger tips.

I am not one to repeat the instructions of others, so here is the link to get fastlane installed on your local machine: Get Started.

Essentially, open your terminal and type those commands into the window and push return. If you face any issues with the first few steps, post below and I’ll try to sync up with you and help.

After running the following command: and choosing the manual setup option:

fastlane init

You will be presented with a few options on how you can setup. I recommend the manual setup process. Don’t worry. It is still automated. Just tap return until the setup process finishes. Once done, you should see a lot of information in your terminal about the fastlane setup. I’d like to highlight the following:

Generated Fastfile at path `./fastlane/Fastfile`
Generated Appfile at path `./fastlane/Appfile`
Gemfile and Gemfile.lock at path `Gemfile`
Please check the newly generated configuration files into git along with your project
This way everyone in your team can benefit from your fastlane setup

You will see a new fastlane directory in the root of your project. This contains the Fastfile and the Appfile . The Fastfile is where you will be coding all of your automation. You can think of the Appfile as a file that contains important information to use in your `Fastfile`.

Fastlane is now installed. Step 1 complete!

Step 2: Creating your first lane

A “lane” can be thought of as a function that can do one or many types of automation tasks. Lanes can even call other lanes just like functions.

Let’s start out by building out a simple test automation task. This task will run your unit tests and your UI tests.

To create your first lane, open up your Fastfile in any code editor.

Note: You’ll notice right away that this code is not written in Objective-C, Swift, Kotlin or Java. Instead, it is written in Ruby. There is a beta version of writing yourFastfile using Swift; however given it is still beta, I have yet to use it.

The syntax of Ruby is different from that of Swift; however, you should be able to follow along and write out a basic Fastlane file with very little understanding of Ruby. As your Fastfile gets more complicated, learning some nuances to Ruby is a good idea.

As you open up your Fastfile you will see some standard code already setup. Go head and copy and paste the bolded code below into your Fastfile between these lines:

default_platform(:ios)platform :ios do
desc "Run Unit and UI Tests"
lane :tests do
scan()
end

end

What this code does is set up a “lane,” that is titled tests which runs the fastlane action scan on your project. Scan is an action (automated task) that has lots of configuration capabilities depending on your project structure, but if you are using a simple starter project, all you need is scan() . You will see desc which is a description that allows you to explain briefly what the lane automates. It is best to keep these descriptions short, as you will see momentarily.

All lanes follow this simple structure.

desc "Custom Brief Description"
lane :lane_name do
action(
action_key : value
)
# Additional lane logic
end

Now it is time to run this automation task. Open up your terminal, make sure you cd into your projects root directory, and type fastlane . This should be your output:

What you can see is that our tests lane is available to run and the desc is listed within the table for an understanding of what that lane does. Enter 1 and let fastlane run your tests.

Assuming your tests are in a good state, you should see a lot of fastlane console output with a final result:

I am using a starter project with the default 2 unit and 2 UI tests

At this point, you might be thinking that the same result can be achieved with a single button click inside of Xcode. You would be right, but you are missing the point.

Step 2 complete! Let’s continue.

Step 3: Adding Additional Automation

Running tests in isolation is a good practice, but what if a fastlane command was triggered by a remote CICD pipeline? What if the build fails due to a bad unit test? In my experience, this should trigger some alert to ensure the unit tests are fixed before merging that code back into a base branch.

At my last three companies, I’ve used Slack as the communication tool between employees. We can leverage this tool by adding another fastlane action slack to our fastlane which will communicate to use about our tests.

First, you need to allow Slack to accept webhooks from your automated tasks. These webhooks give you an authorized URL to use in fastlane to post directly into your Slack workspace. To setup the webhook, go to the Slack Incoming WebHooks Configuration page, allow the integration, and select the channel in the Slack workspace where fastlane should post messages:

Completing this step will give you a webhook URL which you will need reference in the fastlane slack integration.

This has been truncated for privacy purposes, but you will need the full URL

Back to your fastfile, I want you to update your tests lane to the following:

desc "Run Unit and UI Tests"
lane :tests do
begin
scan()
slack(
message: "Tests Passed!",
success: true,
slack_url: "https://hooks.slack.com/..."
)
rescue => exception
slack(
message: "<!here> Tests failed with exception : #{exception}",
success: false,
slack_url: "https://hooks.slack.com/..."
)
end
end

The code above does a number of things:

  1. begin defines the code that you hope to run and pass within your automation process (Ruby language syntax for exceptions here).
  2. rescue => exception captures an exception/error from the previous step if one is encountered during the automation process.
  3. slack() is the fastlane action for interacting with the Slack application’s webhook API.
  4. message , success , and slack_url are a few parameters you need to leverage in order to post properly to slack.
  5. You can see that the success is either true or false . This provides a green or red color to appear in slack to highlight the message as a success or failure.

Note: <!here> is a syntax that can be used in this webhook scenario to replicate the @here alert that is used in Slack.

Now, once this is all hooked up, run the following command in your terminal to trigger your tests lane:

fastlane tests

You should now see the unit tests pass or fail in the console as well as in your slack channel:

You now have notifications, messages, and awareness of your unit test stability all within a single fastlane command. This is much more powerful than the single button click in Xcode to run your tests :) .

Step 3 complete!

Step 4: Add Linting Automation

Another tool that I have found to be very useful is SwiftLint. This is a tool to enforce Swift style and conventions across your application and your team. No more tabs vs spaces debate. Swiftlint will enforce whatever the team defines.

As with the Slack integration, there are a few things needed to setup Swiftlint in your project.

The Github repo’s README.md gives you all the information you need to get setup. My personal recommendation is to use brew (check it here). Once you have SwiftLint installed, make sure you add the Run Script in your project’s build phases (check it here). To add this, tap the + in the top left of your Build Phases tab of your Xcode project.

Here is a screenshot of that last step within the Build Phases section in your Xcode project:

To make sure you set everything up properly, run

swiftlint autocorrect

This should quickly update your project’s basic syntax errors that SwiftLint can automatically correct. You will most likely also see new warnings in your AppDelegate regarding method line_length. If both of these things happen, then you’ve set it up successfully.

Now we want fastlane to run SwiftLint. Open up your Fastlane file again and add the following bold swiftlint() method to your begin block:

...
begin
swiftlint()
scan()
slack(...

Now run fastlane in your terminal again.

fastlane tests

And you should see that the swiftlint is now running as part of your automation process.

This step prevents your teammates from uploading code that has not been properly linted for errors. With proper linting, you gain code consistency by creating a shared understanding among the team as to what is accepted and what is not.

Step 4 Done!

Current State

We now have a single lane that can lint your code, unit and UI test your code, and provide slack messages to your team on success and failure cases. The power that this adds to your workflow is really realized when this fastlane automation can be run on a CICD server such as Bitrise, circleci, or jenkins. If you have properly set up your CICD, you will have an automated process that can be run on every Push or PR creation. This will ensure your integrated code is passing the processes that need to exist in order to merge your code back to a base branch.

Additional Automation and Tips and Tricks

The amount of fastlane automation steps that you can integrate into your workflow feels endless. Your team’s processes and requirements will define how you to set this up to alleviate those tedious tasks and protect your code’s stability.

Fastlane has so many actions you can leverage, but here are a few actions that I really like:

  1. match()Match is a powerful tool that can really alleviate a lot of stress when dealing with provisioning profiles and certificates. It can manage and install your development, ad-hoc, and production certificates automatically. If anything expires, it can automatically update it when you run this command. With great power comes great responsibility. Anyone with experience with iOS development knows that Distribution Certificates are very important, so handing over the management of those files to a fastlane action might be too much for some organizations.
  2. gym()Gym is a widely used fastlane action that archives, signs, and compiles your deployable .ipa file. This in combination with match() can really alleviate a lot of wasted time releasing applications.
  3. increment_build_number()Increment_build_number does exactly what it sounds like. If added to a lane that releases an .ipa file to the App Store, you can feel confident that your build numbers will properly increment and never cause a build to be rejected due to a build number submission issue.
  4. appstore() — The App Store action does exactly what you would expect as well. It uses the .ipa file created from gym() and publishes it to the App Store. What a huge life saver.
  5. sh()Shell commands are very useful in automation. Sometimes you already have shell scripts or CLI commands that trigger workflows, and this command will allow you to continue to leverage those other tools.

A couple additional points to highlight:

  1. Environment Variables: every CICD process has variables that might change between environments or that might be kept as constants within a file. In fastlane, you can define environment variables anywhere in the code so that they are available at future steps:
ENV["USER_EMAIL"] = "patrick@gmail.com"

Once defined, you can then use ENV["USER_EMAIL"] for any value in your fastlane actions or lanes.

2. If your write out a robust enough fastlane, your CICD becomes less relevant. The separation of concerns (automation vs CICD server) and abstraction of dependencies (leveraging any CICD platform) can really be achieved. People in leadership will drool over this if presented correctly ;).

3. The Fastfile is just Ruby, so learning Ruby syntax, variable declaration, control flows and functions can really benefit the organization of this file. This example was written in a very simple way for purposes of the tutorial; however, you could easily organize this code into individual functions with parameters which then kick off certain actions.

Final Thoughts

I was a little hesitant to use fastlane because it was an unknown tool whose value I didn’t really see; however, once I began to automate projects, I began to realize the power it provided. I would highly recommend that you dive deeper into this tool and see how it can help your project or organization. It is also very cool that it supports both iOS and Android. A lot of these lanes can be shared between both platforms.

Community Thoughts?

How have you all used fastlane? What has been the most powerful automation task that you’ve seen be created?

--

--

Rick Owers
Remote iOS Dev

Writer focusing on my career and life experiences: developer, engineering manager, family man, beach lover and dreamer of financial independence.