How to setup FastLane, an easy continuous integration tool for iOS
Fastlane is a collection of tools to automate building and releasing your iOS and Android apps. If you have before tried to deliver apps to TestFlight or the Apple Store, you know how long the process is: archiving the app, export it to the AppleStore, adding the new build (after an infinite processing time), adding screenshots for each device, jumping through a few more hoops and finallyyy, making it available to your tester or to the world
Fastlane puts a lot of great tools together to automate this tedious process and create a chain of commands for testing, building, archiving and publishing your apps. It also allows you to call each one of this tool independently through command line, so you have a lot of freedom in the process. The whole thing looks complicated at first but once you have done it one or 2 times it becomes very simple, and saves a lot of time.
So here is a little tutorial to get you started with Fastlane in iOS.
1. Installing Fastlane on Mac
First of all we are going to install and setup fastlane. Assuming you are on a mac, open the terminal and run each of the following commands:
sudo gem install fastlane --verbose xcode-select --install //this will pop up some actions from xCode gem cleanup
Once you have Fastlane installed, you can add different tools, depending on your needs. Here is the list of fastlane commands from github:
deliver: Upload screenshots, metadata, and your app to the App Store
supply: Upload your Android app and its metadata to Google Play
snapshot: Automate taking localized screenshots of your iOS app on every device
screengrab: Automate taking localized screenshots of your Android app on every device
frameit: Quickly put your screenshots into the right device frames
pem: Automatically generate and renew your push notification profiles
sigh: Because you would rather spend your time building stuff than fighting provisioning
produce: Create new iOS apps on iTunes Connect and Dev Portal using the command line
cert: Automatically create and maintain iOS code signing certificates
spaceship: Ruby library to access the Apple Dev Center and iTunes Connect
pilot: The best way to manage your TestFlight testers and builds from your terminal
boarding: The easiest way to invite your TestFlight beta testers
gym: Building your iOS apps has never been easier
match: Easily sync your certificates and profiles across your team using Git
scan: The easiest way to run tests for your iOS and Mac apps
Each of the product can be installed separately, so just have a look and install the ones you need.
In this example, we are going to install gym (which produce ipa file (build and archive))
sudo gem install gym
By the way, you can also write any custom ruby script you want and launch them in the same way through fastlane.
2. Setting up the Fastlane in your iOS project
Once you have your created your xcode project, go to its folder and run fastlane init . The script will prompt you for your apple ID/password, the app identifier, the scheme, create the app on iTunes Connect and the Apple Developer Port if necessary, and store all this information in fastlane/Appfile and fastlane/Deliverfile.
Once everything is correctly set up, you should see something like that:
Fastlane will then create a folder called `fastlane` with inside a `Fastfile`, which is the ruby configuration script. Here is an example file:
# Customise this file, documentation can be found here: # https://github.com/fastlane/fastlane/tree/master/fastlane/docs # All available actions: https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Actions.md # can also be listed using the `fastlane actions` command # Change the syntax highlighting to Ruby # All lines starting with a # are ignored when running `fastlane` # If you want to automatically update fastlane if a new version is available: # update_fastlane # This is the minimum version number required. # Update this, if you use features of a newer version fastlane_version "1.89.0" default_platform :ios platform :ios do before_all do #test # to setup the proper urls, scroll down to part 3 ENV["SLACK_URL"] ||= "https://hooks.slack.com/services/xxxxxxx" # URL for Project #ios channel #ENV["SLACK_URL"] ||= "https://hooks.slack.com/services/xxxx" slack(message:"New version recieved, processing started") end after_all do |lane| # This block is called, only if the executed lane was successful # slack( # message: "New App Update successfully deployed." # ) end error do |lane, exception| slack( message: exception.message, success: false ) end #lane to run unit tests desc "[TEST] Runs all the tests" lane :unittest do scan end #lane to send app to testflight desc "[TESTFLIGHT] publish production" lane :tf_production do apple_testflight(scheme: "YOUR_SCHEME_NAME") end desc "[STORE] Deploy a new version" lane :app_store do # match(type: "appstore") # snapshot build(scheme:"YOUR_SCHEME_NAME") deliver(force: true) # frameit end desc "[PRIVATE] Deploy a new version to the Testflight" private_lane :apple_testflight do |options| scheme = options[:scheme] slack(message: "Starting processing "+scheme+" for Testflight") cert sigh #TODO: fix "increment_build_number" to bump ONLY the build number or the selected scheme # increment_build_number build(scheme: scheme) resign(signing_identity:'#Name of the certificate as shown in the Keychain, for ex: iPhone Distribution: My COMPANY (XXXXXXXX)') pilot( # distribute_external: false, # testers_file_path:"./external_testers.csv" ) slack(message: "Processing finished") end desc "[PRIVATE] Build usign schema" private_lane :build do |options| scheme = options[:scheme] cocoapods gym( scheme: scheme, codesigning_identity: '#Name of the certificate as shown in the Keychain, for ex: iPhone Distribution: My COMPANY (XXXXXXXX)' ) end end # More information about multiple platforms in fastlane: https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Platforms.md # All available actions: https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Actions.md # fastlane reports which actions are used # No personal data is recorded. Learn more at https://github.com/fastlane/enhancer
Inside this `Fastfile` you have different tools which you can configure. The `Before` and `after` methods are always called, while the `Error` (do) will throw exceptions in case of error.
And are going to start by defining lanes with `desc`.
Here we use Private lanes to abstract the build internally: choose scheme, send slack messages, call cocoapods to install and compile the pods, run gym to build and produce an ipa file, sign download provisionning profile with resign, etc.
As the process go through each command it populate some environment variables which are then used by the next commands. Of course it’s possible to not use private lanes and specify your build scheme manually.
You can find the name of the scheme to specify in your Fastfile in xcode `Manage schemes` at the top, the icon before the one to choose between simulator or device. In 99% of the case targets and schemes are the same, but not always (for instance having the same target with 2 schemes: release and debug), so pick them there.
The exact certificate name shouldn’t be needed if you have only one scheme (FastLane will retrieve it automatically with the commands `cert and `sigh`). In case you need to specify it, you can find the exact certificate name by opening your keychain, selecting the corresponding certificate, right clicking on it, selecting `get info` , and then copying the text in `common name`.
In the metadata folder you can update the information you want to display on the apple store. This is automatically popluated the first time from the info downloaded from the apple store. You can also produce localized screenshots automatically if you have UI testing setup, and the command `frameit` will resizes all of them for each device.
If you haven’t set up the app in itunes connect yet, run produce to create the app in itunes connect and its provisionning profiles.
You also have to add some code in your plist file in xcode (reference here):
Once everything is setup properly, go to your project directory via the terminal, and then run the command `fastlane`. Without anything it will asks which lane you want to run. If you already know it, just type fastlane + platform + scheme name , which would look like this:
fastlane ios tf_production
You will see the all process being displayed (connection to itunes, upload, processing). fastlane –v verbose
Remember to change the build number before running fastlane (there is a beta script doing it but you cannot specify which scheme to use, so it’s a bit useless).
A few more tips:
fastlane –help -> gives you a list of actions in fastlane
fastlane –actions -> description of each action, especially useful to understand how to properly fill the Fastfile.
fastlane –action slack -> see all the parameters for this specific action
3. How to connect Fastlane to Slack
To set up the environnment variable SLACK_URL (https://hooks.slack.services) , you will need to create web hooks in slack.
Go to the slack dashboard : https://api.slack.com/incoming-webhooks, and click on `incoming webhook integration`. If you are logged in in Slack, it will bring you directly to your slack app configuration. Another way to get there is to go to `https://yourchannel.slack.com/apps/manage`, and then -> custom integration -> incoming webhooks
Once you are there you can create a new hooks by clicking on `add configuration` -> `select channel` (or direct message people) _> `Add incoming web hook`, which return a webhook url that you can then paste in your configuration file!
4. Integrating Fastlane with Bamboo
Bamboo is a continuous integration server from Atlassian, the makers of Bitbucket, JIRA, Confluence and Crowd. Bamboo, Bitbucket, and JIRA Software are fully integrated and can give you full traceability from the time a feature request is made all the way to deployment.
To integrate Fastlane with Bamboo you will need to create a build plan (a job). There, you can add a task, and choose the command line tools. There, just setup the path of your local Fastlane installation (binary file), link the task to the repo you want, add a description, and you should be good to go! Feel free to drop me a line if you need more detailed descriptions, I’ll try to make a more in depth post about Bamboo sometimes soon.