Recently IBM took over the mobile applications for one of the largest supermarket chains in Netherlands and I was assigned to the Android application which was created in 2013, a lifetime ago given the pace Android ecosystem been evolving.
Thanks to recent advancements in the development tools like Instant run, IntelliJ-based IDE, SSDs and the x86 emulators, development is much less painful than 5 years ago, but this project was missing a few important things like unit tests, automated tests (mocked & e2e), coding standard checking, code quality analyser and continuous deployment.
This list is a bit of a mouthful, so in this step, I’ll only look at the CI & CD part. while I’ve implemented this many times in other disciplines, I’ve never done this before in Android land. So I decided to blog about it to keep me motivated and to hopefully get some feedback from other developers.
1. Continuous integration with GitLab CI.
2. Build android apk in Docker.
3. Deploy to HockeyApp.
The first step is to create a CI server for development purposes. I don’t have a preference for CI servers but since the project git was setup GitLab I’m using it here. There is a great GitLab Vagrant script here but I had some trouble with SSL, so you can find the modified non SSL version here. Simply type ‘vagrant up’ and follow the steps by going to http://192.168.0.12. You need to create a new project and push your repo to it. eg: ‘git remote add localgitlab [email protected]:root/android.git’ and ‘git push localgitlab’. Now fingers crossed, you should see something like this:
Now goto http://192.168.0.12/admin/runners make a note of the registration token.
A GitLab runner needs to be setup to build your Android project. GitLab runners connect to the GitLab server over http and can be setup on the same box but not recommended since build jobs take a lot of resources and can interfere daily git operations. All the different ways to do this is documented here. I went with the MacOS runner because we share the build box with iOS developers that require a Mac for build and it’s easier to debug on my local Mac. You can follow the steps here for that but don’t use sudo when registering the runner and don’t use sudo when starting the runner as well. I lost a fair amount of time before I came across this post.
Now that we have GitLab CI configured, we need to build the Android apk in a CI environment outside Android Studio and for this, I used a Docker container for a number of reasons including.
- Docker can provide the exact build environment for every build.
- Environment is well documented in the Docker file.
- Easy to update, eg: change the version of ruby and create a new image.
- Faster to develop since only the layers that changed are rebuilt when creating the image using snapshots.
This is the Dockerfile with the dependencies required to build our Android project. I suggest
Now you can create an image from this and upload it to dockerhub that will be used by GitLab CI to create the apk. I suggest you ssh into the Docker container, do a git clone of the project and try to build it using the command line to make sure all the dependencies are there. The image also contains fastlane which is used to upload the apk to HockeyApp shared by iOS and Android. You can generate a fastlane config here, ours is slightly modified to use the API token from an environment variable.
Last but not least, we need the .gitlab-ci.yml in the git root folder to tell gitlab-ci that steps to follow when receiving a new commit. In this above example, we run unit tests on all branches, create a test apk artefact to download on all branches except development and publish apk to HockeyApp only when merged to development.
Next up is adding the missing unit tests, integration tests and end to end tests to the project.