Setting up Fastlane with Ionic/Cordova apps

Recently I was tasked with setting up a build server to build our iOS apps automatically on git push to a certain branch. While the iOS part of this took the majority of my time (Provisioning Profiles, Certs, XCode project files, etc) this will show you how to setup both iOS and Android. I’m writing this because I couldn’t find any guides that worked for Ionic 2/3 and XCode 9. I won’t promise this is the most efficient way (the double iOS building irks me but I haven’t found a away around it yet) or most secure (I’m storing some passwords and certs in the repo and plan to move them out later) but it does work. The steps are essentially the following:

  • Install Fastlane
  • Setup Match (used to manage provisioning profiles and certificates)
  • Get credentials/keys for Google Play
  • Add in hook to “Upgrade” our XCode project file
  • Add platforms/platforms.json to repo
  • Setup your Fastfile (think of it like a makefile/gulpfile/etc)

Some assumptions I’m making:

  • You have XCode CLI tools installed xcode-select --install
  • You have brew installed
  • You have done this the “hard way” before (You have your apps setup in iTunesConnect/Google Play and have uploaded to Testflight and/or Google Play Alpha in the past)
  • You are managing your push notification certs (APNS) yourself, if you want to automate that part look into Pem

Install Fastlane

You can install Fastlane via Bundler but I’m personally not super comfortable with Ruby and I’m not good at debugging issues with it. It’s better (IMHO) to use the brew cask version which comes with all the correct versions of everything. If you are reading this guide after attempting to setup Fastlane on your own and installed it via Bundler I suggest you uninstall that version, I ran into multiple issues with it.

With that out of the way let’s install Fastlane

brew cask install fastlane

Setup Match

I would suggest you create a new iTunesConnect “Admin” user to let Match run under. It needs to have the “Admin” role to do everything it does and you probably don’t want your build server to have a team members credentials on it. You also need to create a new git repo to hold the Provisioning Profiles and Signing Certificates (PP/SC). I’m using a gitlab repo on our self-hosted instance but you can use any private git repo.

Also I am only using Match to manage distribution PP/SC, you can use it for development PP/SC but I personally don’t (I just use XCode automatic signing or that).

Let’s start with initializing Match:

fastlane match init

If you have already created PP/SC in the iOS Dev Center then we need to delete them. DO NOT WORRY, this will not delete your apps or mess up already uploaded iOS builds (released or otherwise). I know it sounds scary but we are going to start off by running:

fastlane match nuke distribution

This will clear out your PP/SC you have for distribution, don’t worry, we are going to create new ones right now:

fastlane match distribution

Okay, we are good to move on setting up our Android certs (you can skip if you only want iOS

Get credentials/keys for Google Play

Things we need for this step:

  • Keystore for signing your Android app (myKeystore.jks)
  • Config file containing for signing (release-signing.properties)
  • Play Credentials (play-credentials.json)

Keystore

This should be self-explanatory, just put this in the root of your app repo.

Config File

Also put this in the root of your app repo. It should look like this:

storeFile=myKeystore.jks
storePassword=XXXyourPasswordHereXXX
keyAlias=XXXyourkeyAliasHereXXX
keyPassword=XXXkeyPasswordHereXXX

Play Credentials

Follow the instructions here and put the resulting JSON file in the root of your app repo.

Add Cordova hook

We need to modify our platforms/ios/My App.xcodeproj/project.pbxproj but we don’t want to have to do it by hand (or by opening XCode) because that would defeat the purpose of a build server and we also don’t want to commit this file to git. What this boils down to one of the Fastlane actions we want to use blows up with a fresh ionic cordova prepare because it thinks the XCode project files is too old. Opening the project in XCode automatically upgrades the file but we need to do it all from the command line. If this pull request has been merged into cordova-ios then this step may no longer be necessary.

The hook we are going to use can be found here:

https://gist.github.com/joshstrange/cfb4128f1be7ac60c22a41dad98ea68a.js

My hook also adds the push notification capability but that should be easy enough to remove if you don’t need it. You will need to edit the it to put your app name instead of “My App”. Once you have added that file to your hooks directory (or wherever you store your hooks) you will need to add the following line into your config.xml file:

<hook src="hooks/add_target_attributes_and_push_notification_cap.js" type="after_prepare" />

You do NOT want to put that inside your iOS platform block. It needs to be at the top level. For some reason Cordova hooks don’t fire inside the platform blocks unless the command you run explicitly mentions a platform. ionic cordova platform add ios will trigger a hook inside the platform block but ionic cordova prepare will not even if/when it adds the missing iOS platform.

Add platforms/platforms.json to repo

Even though I had iOS and Android as engines in the config.xml file Cordova would not pick them up when running ionic cordova prepare. I had to edit my .gitignore and add platforms/platforms.json to my repo:

platforms/*
!platforms/platforms.json

then run

git add platforms/platforms.json

Setup your Fastfile

Copy and paste the following Fastfile into ./fastfile/Fastfile

https://gist.github.com/joshstrange/a3da9901cc84ae7f5d0b1b40dd110e0f.js

Search for “REPLACE ME” for all the places where you need to sub in your own values.

Now you should be able to run:

fastlane ios beta
# OR 
fastlane android alpha

To automatically build and upload to Testflight or Google Play Alpha

Extra: Gitlab CI

We use Gitlab CI and here is the .gitlab-ci.yaml file we use:

https://gist.github.com/joshstrange/b6948d95597a5e9e67623a913baebb50.js

Blog at WordPress.com.