Update (8/31/16): Just wrote a new guide on how to setup Android builds for free using shared runners! Check it out!
Update (8/24/16): This guide is getting a little old! Positive responses from commenters indicate that the guide should still work just fine, but keep in mind that things like specific version numbers or screenshots might not be 100% spot-on. I made some small updates in response to comments, but still plan on doing another walkthrough to fully update this sometime soon :)
I’m a pretty big fan of Gitlab. First off, it’s open source. Big win right there. Second of all, the quality of the project is just insane. It rivals (and sometimes surpasses) Github in terms of features and usability, and blows Bitbucket (a typical go-to for free private repos) out of the water.
On top of that, Gitlab has an open-source continuous integration platform called Gitlab CI. If you’ve never used or heard of continuous integration, I won’t go into the many benefits here - you’ll find plenty of great information about it through a simple search. However, here’s a TL;DR: continuous integration is the practice of having an automated build run upon checking in code. It usually includes things like running unit and/or functional tests, and could even deploy the application after a successful build.
Gitlab has some solid documentation for setting up Gitlab CI for web apps made in Ruby, Python, etc. However, what they don’t have are docs for Android. So, I struggled through the process myself, and here we are!
1. Create an Android project.
For the purpose of this post, I just made a simple project by clicking through the New Project dialog in Android Studio. You can see that project here.
2. Add your project to Gitlab CI.
Go to the Gitlab CI website and create any necessary accounts. Afterwards, find your project in the list and click the “Add project to CI” button. Update (8/24/16): Looks like you no longer have to specifically enable CI for your project! If you go to your project page and click the settings gear in the top right corner, you should be able to see some CI options, like the ability to go to your Runners page.
3. Link a runner.
Click one of the links to go to the runners page for you project.
When you get to the runners page, you’ll see that you have the option to add a specific runner, or use a shared runner. Unfortunately, while there are shared runners for Python and Ruby apps, there aren’t any for Android. That means we’re going to have to setup our own.
I chose to grab a box from Digital Ocean, but you can grab one from anywhere. The smallest instance should be ok, but I ended up going with the 1GB of RAM.
Ok, now that you have a box, we can install the Gitlab CI runner software. We’ll be installing the Official Gitlab Runner in Go. There’s guides on that page to install Gitlab CI on various operating systems. I grabbed an Ubuntu 14.04 box from Digital Ocean, so I followed the Linux Guide. For convenience, the steps are:
# Add Gitlab repository curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-ci-multi-runner/script.deb.sh | sudo bash # Install the runner software apt-get install gitlab-ci-multi-runner
Awesome! You officially have the runner software installed. Next, we have to register your project with this runner.
First, get your registration token. You should see this on your runners page. Write this down somewhere - we’ll be using it during our runner setup process.
Now you can go back to your runner box and run the following command:
sudo gitlab-ci-multi-runner register
Ok, so now the registration process is going to ask you a bunch of questions. Let’s walk through them.
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/ci )
Per their suggestions, just use https://gitlab.com/ci if you’re using the public gitlab instance. However, if you have a self-hosted instance, be sure to use http://your-gitlab-host.com/ci.
Please enter the gitlab-ci token for this runner
Remember that registration token I told you to write down earlier? This is when you use it.
Please enter the gitlab-ci description for this runner
You can use whatever name you want, and you can also change it later on the Gitlab CI site. I just chose “gitlab-temp-runner”.
INFO fcf5c619 Registering runner... succeeded Please enter the executor: shell, docker, docker-ssh, ssh?
Shell (although I really do want to setup a docker container for Android to make this process easier).
INFO Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
You’re good to go! If you refresh you runners page for your project, you should see a new runner added under “Specific Runners.”
Congrats! You’ve got a runner linked to your project. Any new commits to your repo will now trigger builds… and those builds will fail, because they don’t do anything. Let’s fix that.
4. Install the Android SDK on your runner.
Google’s made it relatively easy to install Android on a machine that has an actual graphical interface. Installing it on a headless box… not so much - but the tools are, in fact, there! So let’s do this.
First, we need the SDK. You can find the install for your OS here. For Ubuntu, you’ll want to use the url of the Linux download.
Now let’s download and extract our SDK files to our server. In your directory of choice, run:
# Download the compressed file wget <url> # Extract the contents tar zxvf <sdk filename>.tgz
Ok, so now we want to put the SDK somewhere that makes sense. Let’s plop it down in
mv android-sdk-linux /opt/android-sdk cd /opt/android-sdk
Now that we have the SDK in a good spot, let’s install our build tools. But before we can do that, let’s make sure we have java installed, which is necessary to both build our project and install the various SDK components.
If you’re also using an Ubuntu 14.04 DigitalOcean box, you’ll find out that java is not installed, but it gives you a helpful hint to install the default-jre package, so let’s install that, as well as the jdk (If you already have java installed, you can obviously skip this step).
sudo apt-get install default-jre sudo apt-get install default-jdk
Now that we’ve got that over with, let’s install the necessary tools. The Android SDK includes an executable called “android” that allows us to list and install the various SDK components that you’d normally install with a GUI using the SDK Manager in Android Studio.
First, we’ll run a command that will let us see all the packages available for download.
tools/android list sdk -a
That’ll give you a big ‘ol list of packages, each with a number. Make note of the packages you want to install. I’m compiling my test project with
buildToolsVersion 23.0.1, so I’m going to install:
- Android SDK Tools, revision 24.4
- Android SDK Platform-tools, revision 23.0.1
- Android SDK Build-tools, revision 23.0.1
- SDK Platform Android 6.0, API 23, revision 1
- Android Support Repository, revision 21
- Android Support Library, revision 23.0.1
Once you’ve chosen your own set of packages, run:
tools/android update sdk -a -u -t 1,2,3
Hint: You can include the -n flag to do a dry-run install to make sure you chose your packages correctly.
Where “1,2,3” is the list of packages indices you want to install.
Now, normally, you’d be done and ready to build. However, if you’re on 64-bit Ubuntu, you have one more step: we have to install the 32-bit runtimes in order for the Android build tools to work correctly. To do that, just run the following:
sudo dpkg --add-architecture i386 sudo apt-get -qqy update sudo apt-get -qqy install libncurses5:i386 libstdc++6:i386 zlib1g:i386
That will allow our Android tools to run perfectly on our 64-bit architecture. Ok, almost done!
5. Write your build configuration file.
Gitlab CI uses a build configuration file to describe to the runner what it needs to do to build your project. That file is called
.gitlab-ci.yml and lives in the root directory of your project. Here’s the file for my test project:
before_script: - export ANDROID_HOME="/opt/android-sdk" dev: script: - ./gradlew assembleDebug
Update (8/24/16): While this worked for me, some commenters reported having to add ‘chmod +x gradlew’ as an extra step in the script to make gradlew executable.
Simply put, before the build runs, we’re going to set our ANDROID_HOME environment variable to our SDK location. We also setup a task called
dev that builds the project by running
./gradlew assembleDebug. Therefore, our build will pass if the project builds correctly, and it will fail if it doesn’t. A simple build configuration for sure, but you can have it do much more by running unit and functional tests. I hope to dive into that more in a future post.
6. Push your changes and watch the magic happen!
At this point, you can commit your
.gitlab-ci.yml, push your code, and watch the build run!
If you want a little build-status badge for your project, you can add the following Markdown to your README.md:
![Build Status](https://ci.gitlab.com/projects/<project number>/status.png?ref=master)
You can find your project number in your url for Gitlab CI. It should look something like
https://gitlab.com/ci/projects/<project number>. You can see the README.md of my sample project for an example