Changing Lanes - Mobile Development Deployment - Android

By Snack Overflow
Last updated: 16.05.2017
mobile android CI CD Jenkins Fastlane

Stuck in the slow lane

Our process for buiding and releasing our application fell onto the shoulders of just one developer using one configured laptop. It wasn't until he went on holiday and we needed to update the application that we realised this had to change and change fast. This is when we found out about fastlane.

fastlane promises a collection of tools which allow for automating the building and releasing of android and iOS applications. Their actual quote was

fastlane lets you define and run your deployment pipelines for different environments. It helps you unify your app’s release process and automate the whole process. fastlane connects all fastlane tools and third party tools, like CocoaPods and Gradle.

At the time of writing, this isn't entirely true in our opinion. Android support is limited to pushing applications to the Google Play Store and managing the meta information i.e. screen shots, textual descriptions, app icons etc. With the announcement that fastlane is now part of the Fabric.io team the support might catch-up to the level of iOS.

Moving into the Fastlane

We decided to pick one of our Android mobile apps first as this seemed to be a quicker path to getting started with fastlane. We were already using Jenkins as our Continuous Integration Server and it has worked well for us so that was going to be the tool to run our builds.

fastlane requires, at the time of writing, Ruby 2.0.0 as a minimum so that needs to be installed. We decided to installed RVM (Ruby Version Manager) which allows us to have different Ruby environments so we can test newer versions of fastlane as they come out and isolate our working version set.

Jenkins

We already use Jenkins to build all our production code and so decided to stick with what we knew. We installed a new instance of Jenkins to isolate our existing builds. There is a Ruby gem for Jenkins and since Ruby is a requirement for fastlane, we used it.

Install Jenkins:

$sudo gem install jenkins-war

$sudo gem install Jenkins

This last install allows us to control Jenkins from the command line, specifically starting and stopping.

To run an instance of Jenkins which is then available on port 3001:

$jenkins server

Once it's running it creates a .jenkins folder in the current user's home directory to store its configuration files.

To run an instance of Jenkins as a daemon and also to stop it:

$jenkins server --daemon

$jenkins server -k

Our project is maintained in our source control server so we had to configure Jenkins to have access to it. We already had SSH keys for the Jenkins user so we just needed to configure Jenkins to use them. 

We added our credentials under the Credentials -> Global credentials -> Add Credentials > Kind (SSH Username with private key).

Android SDK

This is included with the Android Studio application but since we were configuring our server which had no UI installed we downloaded the SDK separately on the command line and installed it.

If you're using Android Studio/SDK Manager checkout the official User Guide:

$wget http://dl.google.com/android/android-sdk_r24.4.1-linux.tgz

This link might be out of date now, so check the Android Downloads page.

Extract the goodness into the current users home directory:

$tar zxvf android-sdk_r24.4.1-linux.tgz

After installing we could then go and install the Android API, Build Tools & Platform Tools.

This gives you a list of all available packages to install:

$android list sdk --all

 

From the generated list you install packages via the following command:

$android update sdk -u -a -t <package_id>

 

We had to install amongst others:

  • Google APIs, Android API 23, revision 1

  • Local Maven repository for Support Libraries, revision 28

  • Android Support Library, revision 23.2.1

  • Google Play services, revision 29

  • Google Repository, revision 25

  • Google Play Licensing Library, revision 2

fastlane

Install fastlane with:

$sudo gem install fastlane -NW

To get started with fastlane you must first initialise a project to use it and then create some lanes to run.

Initialising a project is as simple as running the following in the root of your project:

$fastlane init

This will ask some questions about your project and if you want to set up certain things, which you can answer no to and set up later on.

For a full step by step setup refer to the fastlane documentation Getting started with fastlane for Android.

Lanes

fastlane has this concept of lanes. A lane is a set of commands/tasks that will define your processes.
With our application being a hybrid application based on the Ionic framework, we tried to find some means of integrating fastlane and Ionic and couldn't. To get around this we created a set of scripts which did all the Ionic stuff and then used the tools supplied by fastlane for everything else.
We created 2 scripts:
  • ionic_build_unsigned.sh
  • ionic_build_signed.sh
These generated the apk files which we could then use fastlane to:
  • publish to Crashlytics
  • publish to GooglePlay store
  • send notification to our slack channel.
We have 3 lanes currently:
  • build unsigned release
  • build unsigned releases and publish to crashlytics and notify a slack channel
  • build signed releases and publish to GooglePlay store and notify a slack channel

 

Our Fastfile looks like this

fastlane_version "1.68.0"
default_platform :android
platform :android do
  # Build
  lane :build do
   # Build unsigned APK
    sh "ionic_build_unsigned.sh"
  end
  # Build, Sign and Publish to crashlytics
  lane :crashlytics do
    # Build signed APK
    sh "ionic_build_signed.sh"
    desc "Submit a new Beta Build to Crashlytics Beta"
    crashlytics(
      groups: "*****",
      apk_path: "platforms/android/build/outputs/apk/******.apk",
      crashlytics_path: "etc/crashlytics-devtools.jar"
    )

    # Post Slack notification
    slack(
      channel: "hpi_trade_ci",
      default_payloads: [],
      message: "A new beta distributed of '******' for Android is now ready on http://fabric.io",
      attachment_properties: {
        thumb_url: 'https://raw.githubusercontent.com/fastlane/fastlane/master/fastlane/assets/fastlane.png'
      }
    )

  end
 

 # Build, Sign and Publish to Play Store
 lane :play_alpha do
    # Build signed APK
    sh "ionic_build_signed.sh"
    # Upload to Google Play store
    supply(
      skip_upload_metadata: true,
      skip_upload_images: true,
      skip_upload_screenshots: true,
      track: "alpha",
      apk: "platforms/android/build/outputs/apk/******.apk"
    )
    # Post Slack notification
    slack(
      channel: "******",
      default_payloads: [],
      message: "A new alpha distributed of ***** for Android is now ready on Google PlayStore https://play.google.com",
      attachment_properties: {
        thumb_url: 'https://raw.githubusercontent.com/fastlane/fastlane/master/fastlane/assets/fastlane.png'
      }
    )

  end

Configuring Jenkins

Running the fastlane lanes in Jenkins is simply achieved by using the Jenkins 'Execute shell' build step.

 

 

We capture all the build artifacts which are built into the platforms/android/build/outputs/apk/ directory.

 

Clear Road Ahead

We have been running with fastlane for a while and it just takes away the pain of building, delivering and notifying people of new releases. We can concentrate on developing new features without having to break away to create builds. Not only have we rolled this out for our Android builds we have also rolled this out for our iOS builds too.