How to make iOS development faster? Continuous Integration using Fastlane and Jenkins

Being the first iOS developer at Blast Lab is an honorable and challenging role. When I started, it required to creating the whole process of iOS development for a company and today I would like to share my knowledge and thoughts after 3 years of being the main iOS developer.

The whole idea behind this post is to give you a ready-to-implement solution. Build server is any computer, which runs on macOS. Jenkins connects with this computer and the application is compiled here. So the whole scheme behind this process look like this:

So let’s start with Fastlane!

Fastlane is a tool made to automate beta deployments and releases for iOS (and Android) apps. It helps to save a lot of time on regular tasks and gives more clarity by sharing those tasks configuration with code. So after set up, you can focus on code.

You need to do it on both — your computer and on the build server.

Update Ruby to the 2.0 or higher version, because the older versions don’t support TLS 1.2, which is required to connect to iTunes.

Homebrew installation and Ruby upgrade:

/usr/bin/ruby -e “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"'
brew install rbenv
brew install ruby-build
# Add rbenv to bash so that it loads every time you open a terminal
echo ‘if which rbenv > /dev/null; then eval “$(rbenv init -)”; fi’ >> ~/.bash_profile
source ~/.bash_profile
# Install Ruby
rbenv install 2.4.1
rbenv global 2.4.1
ruby -v

2.4.1 is the newest version of Ruby at the moment. You can find latest stable release here: https://www.ruby-lang.org/en/downloads/

Then you can finally instal Fastlane:

brew cask install fastlane

From this moment, you work on your computer:

Now, when you installed FastLane, you need to initialize it in your project. So go to your project directory and type:

fastlane init

Adding different Dev accounts and iTunesConnect

Firstly, you need to generate a Dev account on developer.apple.com and iTunes Connect user. You need to register on both with the dedicated developer’s email, which will be used by build server (in our case it is “buildserver@blastlab.co”). In <project dir>/fastlane/Appfile you need to add the lines with accounts you created:

apple_id "buildserver@blastlab.co"
itunes_connect_id "buildserver@blastlab.co"

E-mail address which you added here is the mail which we are going to use to create a dev account.

Remember! You need to add all of the accounts to the keychain on your local machine!

In <project dir>/fastlane/Fastfile you need to add these lines with accounts which you created above:

fastlane_version "1.111.0"
default_platform :ios
platform :ios do
desc "Submit a new Beta Build to Apple TestFlight"
  lane :beta do
    scan
    gym(scheme:"your app bundle")
    pilot(skip_waiting_for_build_processing:true)
  end
end

Certificates:

Now you have to generate certificates for your build server — iOS distribution, which allows you to create development apps and certificate for every app, which you want to build. You choose both here:

Then you need to choose right Scheme in Xcode…

…and tick “Shared”:

Now you need to configure build server and add Certificates

In this case, I used a Macbook. It has to be always online so Jenkins would be able to connect with it. When new commit appears, Jenkins will automatically build a new version of app.

To add certificates to your build server, you need to copy them and double click them. So macOS will ask you if you want to add them to the keychain.

Share an access for local commands

Jenkins connects to build server via SSH. To provide it an access to use Ruby and RVM, you need to add:

export PATH="$PATH:$HOME/.rvm/bin" # Add RVM to PATH for scripting

To PATH variable in the ~/.bashrc file.

Adding Dev account and iTunesConnect

Add both to the Keychain (assuming that both accounts use the same email address):

fastlane fastlane-credentials add --username buildserver@blastlab.co

Instead of buildserver@blastlab.co write dev e-mail.

Read more about Fastlane here:

fastlane/fastlane

Permission to connect to the computer via SSH

Do it on the build server.

To allows Jenkins to connect with the computer and to execute operations from fastline, you need to allow remote connection with the computer:

System Preferences > Sharing > Tick "Remote Login"

And integrate it all via Jenkins!

On Jenkins install Publish Over SSH plugin.

Now you need to configure connection with the build server.

In Jenkins system configuration, in “Publish over SSH” section, configure new SSH connection to the build server.

Create Jenkins’s job

You need to create Jenkins’s job and, as always, configure your app’s code repository that will be monitored.

In Build section add a step “Send files or execute commands over SSH”.

Choose the connection with the build server which you have already created.

In transfers section add two new transfer sets.

First one:

  • In “Exec command” you add rm -rf $JOB_NAME — it tells Jenkins to clear old files in the previous job.

Then in the second one (copy files to build server and execute fastlane build):

  • In “Source files” when you use ** you pick up all the files in this job,
  • Remote directory is the place when you copy your whole repository — we suggest putting your job’s name here to identify it and prevent conflicts,
  • You need to enter your project’s directory and execute Fastlane’s build,

Here is an example of the command:

cd $JOB_NAME/AppName && fastlane beta

If your Fastlane’s build use some scripts, this scripts loose their permission to execute during the coping. In this case, in your command you need to:

  • unlock keychain security unlock-keychain -p JenkinsCi ~/Library/Keychains/login.keychain,
  • add execution permissions to these scripts. In our case, we add them for Fabric and Crashlytics.

Example of the whole command:

cd $JOB_NAME/PerfectaControl &&security unlock-keychain -p JenkinsCi ~/Library/Keychains/login.keychain && chmod +x Fabric.framework/run && chmod +x Fabric.framework/uploadDSYM && chmod +x Crashlytics.framework/run && chmod +x Crashlytics.framework/uploadDSYM && fastlane beta

JenkinsCi is the name of the local user.

Example of our configuration

Useful tip: Lengthen execution timeout of the job!

Useful tip: How to always have the latest version of FastLane?

In my case, I created a job on Jenkins to do it automatically. How it’s done?

You need to have your server already setup.

Firstly, create your job:

In “Exec command” add: gem update fastlane && gem cleanup

Then, configure it to run every day at 3 AM:

Set up notifications:

Finally, you are always notified if all is going well with your Jenkins 🙂

First start of Fastlane

I suggest to manually start fastlane for the first time. So you would be able to grant the required permissions(i. e. access to keychain, authorization of the new machine)

If your server runs on MacBook this could be useful:

Even if you turn off auto-sleep mode in Preferences on your Macbook, it will turn it on anyway. How to prevent it?

Use some third-party app, because Apple does not provide any solution. Check this out:

Google Code Archive – Long-term storage for Google Code Project Hosting.

What about TravisCl?

It is quite good, but I didn’t want to send our code to the third-party server. Obviously, it is easier to use, because Travis has its own server administration, which takes care of their machines. But I don’t want to send sensitive data anywhere else that it is necessary.

Hopefully, this tutorial would help you bring iOS development to the next level 🙂

Author: Tomasz Piernicki —iOS Developer at BlastLab Ltd. Always focused on building the best mobile apps for iOS. He also develops apps for Tizen and Android.

Join our Hardware group and support Polish community!

Like our fan page,

Follow us on Twitter,

And click this ❤ if you like what you read!


How to make iOS development faster? Continuous Integration using Fastlane and Jenkins was originally published in The Official BlastLab Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.