Continuous Integration with Android and Bamboo

By Craig Thomas, Tue 14 October 2014, in category Continuous integration

android, bamboo, ci, emulator

In a previous post, I spoke about how to use Robolectric to unit test Android applications without having to resort to the emulator. In this post, I’ll detail setting up Atlassian Bamboo to run continuous integration of an Android application.

What is Bamboo?

For those of you who don’t know, Atlassian Bamboo is a Continuous Integration system. Many people have probably heard of Confluence (think internal wiki and collaboration software), Stash (now BitBucket) or JIRA (issue tracking software). These three systems are widely used in Enterprise software development shops and many businesses in general.

To me, Bamboo is a vital key in the software development process. Combining Bamboo with JIRA and Stash provides some really great features, such as creating task branches directly from your issue tracking software, seeing what issues were resolved with a commit, and being able to track released versions with all of their fixes detailed in a nice changelog.

The Problem

When performing Android development, I needed to get Bamboo building my projects. Doing so involved two separate pieces:

  1. Installing the Android SDK so that Bamboo had access to it.
  2. Configuring Bamboo to build the actual project.

Note that I’m assuming that you already have a JDK installed on the server, and that you’ve already installed Bamboo.

Installing the Android SDK

This task was fairly straight-forward. First, I had to download the actual Android SDK from Google’s website. This meant visiting the Android SDK website, and then clicking on View all downloads and sizes. I just wanted the SDK tools, not the ADT bundle, so I selected the android-sdk_r23.0.2-linux.tgz package which was about 140 MB in size (note that when you read this, the SDK may be several versions more advanced – your mileage, therefore, may vary).

Once downloaded, I copied it up to my server, and expanded it in a place where all users of the server could access it:

sudo mkdir /opt/android
cd /opt/android
sudo tar xvzf ~thomas/android-sdk_r23.0.2-linux.tgz

This expanded the SDK to the /opt/android/android-sdk-linux directory. I then fired up the SDK manager to install the necessary components. First though, I had to log out, and then SSH with X-11 forwarding turned on so that I could see the GUI it provides (note that you can do everything without the GUI using the --no-ui option for the android update sdk command):

ssh -X 10.0.0.60

Next, I actually ran the android tool as root:

sudo /opt/android/android-sdk-linux/tools/android

However, this resulted in an error message:

Exception in thread "main" java.lang.UnsatisfiedLinkError: no swt-pi-gtk-3550 or swt-pi-gtk in swt.library.path, java.library.path or the jar file
    at org.eclipse.swt.internal.Library.loadLibrary(Unknown Source)
    at org.eclipse.swt.internal.Library.loadLibrary(Unknown Source)
    at org.eclipse.swt.internal.gtk.OS.(Unknown Source)
    at org.eclipse.swt.internal.Converter.wcsToMbcs(Unknown Source)
    at org.eclipse.swt.internal.Converter.wcsToMbcs(Unknown Source)
    at org.eclipse.swt.widgets.Display.(Unknown Source)
    at com.android.sdkmanager.Main.showSdkManagerWindow(Main.java:402)
    at com.android.sdkmanager.Main.doAction(Main.java:390)
    at com.android.sdkmanager.Main.run(Main.java:150)
    at com.android.sdkmanager.Main.main(Main.java:116)

The quickest way to solve this problem (as discussed here), was to install the libswt-gtk-3-java package:

sudo apt-get update
sudo apt-get install sudo apt-get install libswt-gtk-3-java

I then re-ran the SDK manager:

sudo /opt/android/android-sdk-linux/tools/android

And got the normal SDK manager window up. I then proceeded to install the components I needed as usual:

Android SDK Window

Configuring Bamboo

The next step was to configure Bamboo to actually perform the build. I went ahead and created a new Plan for my code repository. When configuring the tasks, I left the default Stage in place. Under the default stage, I left the default Source Code Checkout task in place, but added a new task to perform the build. Because I was using Gradle, I created a Script task:

Bamboo Script Task

The script task required only two pieces of information. For the actual script, I used the Gradle wrapper that I had checked into source code control, and used the build target (./gradlew build). In addition to that, I had to tell the script where the Android SDK was located. For that, I created an environment variable called ANDROID_HOME and set it to where the SDK was located. Here is a screenshot of the configured task:

Specifying the Gradle Target

When I first ran the build, I was surprised that no test results were being reported, even though the build target in the Gradle wrapper runs the actual unit tests. I realized I needed to use a JUnit Parser task to parse the test results. All that was needed for that was to specify the directory where the results of the unit tests would be located. I did that with a simple ANT-style path:

**/test-results/*.xml

Here is a screenshot of the configured JUnit Parser task:

Specifying the JUnit Parser Configuration

With that complete, I triggered a manual build, and checked the test results tab to make sure everything ran:

Test Results

83 tests run, all successful. Excellent!

Wrapping Up

As you can see, it is fairly straightforward to get simple unit testing going on Bamboo with the Android SDK. This assumes of course, that you don’t actually need the emulator, and are using a package such as Robolectric. In a future post, I’ll talk about some more of the challenges of developing a CI strategy with the Android SDK, and how to solve them.