Here at weLaika we loved Capistrano - and we still love it, because it’s easy and complete. When we started to develop and deploy Rails applications, we appreciated its help to build and deploy complex applications.
When we began to work in WordPress ecosystem, we didn’t find any “Capistrano” tool, so we developed it Wordmove.
But is there a “Capistrano” for mobile applications? Is there a tool that can help us to deploy mobile application to stores? Yes, and it’s called fastlane.
Fastlane
Fastlane is a set of Ruby gems that help to simplify and automate the app deployment and release process within a single streamlined workflow¹: by creating a custom list of sequential build tasks called lanes and using the tools provided, called actions, you are able to deploy to App Store / Play Store with a single command line.
The result is that you can do more frequent, and smaller, releases that can be deployed by anyone in your team, using a simple configuration.
Requirements
First, to get fastlane up and running, we need:
- OSX / macOS Sierra
- Ruby 2.0 or newer
- Xcode (for iOS builds)
- Android SDK (for Android builds)
- Paid Apple Developer Account (for iOS builds)
- Paid Google Developer Account (for Android builds)
Since fastlane is a collection of Ruby scripts, you must have the right version of Ruby installed (2.0.0). OS X 10.9 (Mavericks) and later come with Ruby 2.0. Check this out with this command:
1
$ ruby -v
To check whether the Xcode Command Line Tools (CLT) are installed, type:
1
$ xcode-select --install
If the Xcode CLTs are already installed, you will get this error:
1
xcode-select: error: command line tools are already installed, use "Software Update" to install updates
If not, Terminal will go ahead and install the Xcode CLTs for you.
To build an APK you’ll need to have on your development machine the Android SDK. If you don’t have it, you can install it using homebrew
1
brew install android-sdk
Next, run the “Android SDK Manager”
1
android
And install at least the Android SDK tools
, Android SDK platform-tools
, Android SDK Build tools
.
Getting started
We will use the Ionic v2 tutorial app as sample app; if you don’t know how to use Ionic read the Ionic installation tutorial and come back!
1
2
3
$ ionic start MyFastlaneDemo tutorial --v2
$ cd MyFastlaneDemo
$ ionic state restore
Setup
To install fastlane globally run
1
$ sudo gem install fastlane --verbose
Then run this command inside the root folder of your Ionic app
1
$ fastlane init
Fastlane will ask for your Apple ID and other information, and then it generates a fastlane configuration based on the information you provided.
When fastlane asks
1
Couldn't automatically detect the project file, please provide a path:
that’s because fastlane tries to find the Xcode project in the root folder - but in a ionic project it’s inside the platforms/ios/
folder, so in this example it will be platforms/ios/MyFastlaneDemo.xcodeproj
(replace MyFastlaneDemo
with the name of the project if you changed it, of course).
Fastlane, after the login with your Apple ID, will try also to create the app on iTunes Connect for you.
If you need more info on setting up fastlane, there is a good quick-start section in fastlane documentation.
The configuration file, fastlane/Appfile
, will contains all the essential information and fastlane/Fastlane
will contains lanes and actions that are needed to release your app.
The Fastlane
file will looks like
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
default_platform :ios
platform :ios do
desc "Submit a new Beta Build to Apple TestFlight"
desc "This will also make sure the profile is up to date"
lane :beta do
# match(type: "appstore") # more information: https://codesigning.guide
gym # Build your app - more options available
end
desc "Deploy a new version to the App Store"
lane :release do
# match(type: "appstore")
# snapshot
gym # Build your app - more options available
deliver(force: true)
end
# You can define as many lanes as you want
end
iOS build
Fastlane has been developed for iOS projects and it contains everything you need to build and deploy iOS apps.
We are in a team and therefore we need to easily sync our certificates and profiles across us: thanks to fastlane Match we can use a GIT repo. Run
1
$ match init
and follow the usage instruction in Match documentation.
The build process for an iOS app contains several steps: sync of our certificates and profiles, build of the app using Ionic, and packing everything.
Replace the platform iOS section with the following lines:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
platform :ios do
desc "Compile a new build for for appstore"
lane :release do
app_name_sanitized = 'MyFastlaneDemo'
ios_project_path = "platforms/ios/#{app_name_sanitized}.xcodeproj"
# Compile the ionic app
sh("ionic build ios --release")
# Get certificate
cert
# Get provisioning profile
match(type: "appstore", app_identifier: app_identifier, readonly: true)
sigh(
force: false
)
# Recreate schemes to ensure a smooth transition from cordova to gym
recreate_schemes(
project: ios_project_path
)
# Archive app into ipa
gym(
scheme: app_name_sanitized,
project: ios_project_path,
export_method: 'app-store'
)
end
end
You can create another lane
to build, for example, the ad-hoc
release: you just need to set correctly some variables.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[...]
# Get certificate
cert
# Get provisioning profile
match(type: "adhoc", app_identifier: app_identifier, readonly: true)
sigh(
adhoc: true,
force: false
)
# Recreate schemes to ensure a smooth transition from cordova to gym
recreate_schemes(
project: ios_project_path
)
# Archive app into ipa
gym(
scheme: app_name_sanitized,
project: ios_project_path,
export_method: 'ad-hoc'
)
Android lanes
Thanks to AppFoundry you can add some actions to build Android apps correctly: copy sign_apk.rb
and zipalign.rb
from their Github repo to your fastlane/actions
folder. You will get
1
2
$ ls fastlane/actions/
sign_apk.rb zipalign.rb
Add the following lines to your .gitignore
file:
1
2
3
# Fastlane
fastlane/.env
fastlane/release-cred/*.keystore
Create a .env
file inside the fastlane
folder and add there the KEY_PASS
and STORE_PASS
variables, that contain the keystore password and the store password. For example
1
2
KEY_PASS = "qwertyuiop1234567890"
STORE_PASS = "qwertyuiop1234567890"
Create the folder release-cred
and there you must add the Android keystore file (if you don’t have one, you can create it via command-line.
Now we have all the actions we need to automatize the build process for Android.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
platform :android do
desc "Compile a new build for Android"
lane :release do |options|
app_android_key = 'MyFastlaneDemo'
ssh("ionic build android --release")
sign_apk(
apk_path: "platforms/android/build/outputs/apk/android-release-unsigned.apk",
signed_apk_path: "platforms/android/build/outputs/apk/android-release-signed.apk",
keystore_path: "fastlane/release-cred/android.keystore",
alias: app_android_key,
)
zipalign(apk_path: "#{lane_context[SharedValues::SIGNED_APK_PATH]}")
end
end
Let’s build'em
You can now run fastlane using
1
$ fastlane ios release
or
1
$ fastlane android release
and wait for them to be compiled.
Add magic stuffs
We use Crosswalk in our hybrid projects, so we can build two Android apks: one for x86 and another one for armv7. Thanks to fastlane we can automatize that with two private lanes and use them in the main lane.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
desc "Do a new arm v7 Android build using jarsigner and zipalign."
private_lane :android_arm_release do |options|
sign_apk(
apk_path: "platforms/android/build/outputs/apk/android-armv7-release-unsigned.apk",
signed_apk_path: "platforms/android/build/outputs/apk/android-armv7-release-signed.apk",
keystore_path: "fastlane/release-cred/android.keystore",
alias: app_android_key,
)
zipalign(apk_path: "#{lane_context[SharedValues::SIGNED_APK_PATH]}")
end
desc "Do a new x86 Android build using jarsigner and zipaliagn."
private_lane :android_x86_release do |options|
sign_apk(
apk_path: "platforms/android/build/outputs/apk/android-x86-release-unsigned.apk",
signed_apk_path: "platforms/android/build/outputs/apk/android-x86-release-signed.apk",
keystore_path: "fastlane/release-cred/android.keystore",
alias: app_android_key,
)
zipalign(apk_path: "#{lane_context[SharedValues::SIGNED_APK_PATH]}")
end
You can also deploy a new beta build to HockeyApp and automatically notify the projects’ HipChat room:
1
2
3
4
5
hockey(
api_token: ENV['HOCKEY_IOS_API_TOKEN'],
ipa: "./releases/#{app_name_sanitized}.ipa"
)
hipchat(message: "Successfully deployed a new <b>iOS</b> build to HockeyApp<br/><a href='#{lane_context[SharedValues::HOCKEY_DOWNLOAD_LINK]}'>#{lane_context[SharedValues::HOCKEY_DOWNLOAD_LINK]}</a>")
In this snippet, Gym builds the IPA in a specific folder of the project, and the actions for HockeyApp and HipChat have been configured within the environment file.
You can integrate the build process with a lot of external services: you can find a list on fastlane documentation page, for example Slack/Flock/Email/Notification, Crashlytics, or tagging the git repo with the version of the build.
You can also release the build directly to iTunes Connect (documentation) or to the Play Developer Console (documentation).
Checkout the fastlane examples to learn how to integrate all these actions in a real-world mobile application.