I’m a big fan of Continuous Integration/Continuous Delivery. Continuous Integration gives us more confidence in our code by helping us to identify bugs earlier in the development lifecycle. With Software Maintenance representing up to 90% of the total cost of ownership for software, the sooner a bug is found in the process the less frustration, time, and energy that will be needed to fix the bug. This can have any number of downstream effects including purposefully or inadvertently creating code that works around or becomes dependent upon the bug.
Continuous Integration also encourages us to check in early and check in often. Checking in early and often helps us decrease the surface area of our change, thus decreasing the amount of code that can introduce bugs in the system. Checking in early and check in often becomes even more effective when it’s coupled with unit/behavior tests. Having unit/behavior tests allow us to ensure consistency in functionality and behavior across changes. It gives us the confidence that our change, no matter how small, hasn’t changed the behavior of the system. It also allows us to ensure that previous bug fixes and features continue to work as designed. Most importantly, having tests allows you to identify areas of the code that can be cleaned up, refactored, or just don’t behave as expected.
So you may be asking yourself what all this has to do with automating builds for AndroidTM applications. Strictly speaking automating Android application builds consists of:
- Having a machine setup with the latest version of your software (and optionally signing certificate for release builds)
- Triggering a build given some set of conditions
- Archiving the build somewhere.
Here’s where the introductory paragraphs become important. I would argue that having a reliable automated Android application build consists of the following in addition to the minimum requirements above:
- Having your source version controlled
- Having unit/behavior/integration tests that verify the functionality of your software
- Being able to trigger an Android application build from source control commits and have that build run the tests each time.
That’s exactly the system we’ve built here at InfoSpace to automate our Android application builds. Here’s a high level walk through of our automated build process.
Our workflow varies per Android project depending on the build task (building and testing our libraries, building our release APK’s, or etc).
The first gotcha is that the built-in Android application build test ant task ALWAYS returns a success exit code for its process regardless of whether or not the tests fail. This means that we can’t fail the build during the test portion of the build process if the project compiles but fails the tests.
The second gotcha is that you can’t run any of the ant tasks in the post build process. If we could do that then we’d have a way to work around the first gotcha by running the “Text Finder” plugin, which will fail the build, before running the ant task to build the release bits.
So what we’re stuck with right now is a scenario which isn’t ideal but is functional. If someone checks in code that compiles but doesn’t work functionally (i.e. the tests fail) it will still drop the release bits to our Dropbox archive. But we’ll get notified that the build failed and know not to use those release bits. Dropbox allows for file history so we can get the last known good build from Dropbox. But in the even that we can’t get it on Dropbox we take advantage of the ability to archive the build bits via the Jenkins project directly on the build server. If we needed to we could always go back and get the last known good build directly from Jenkins.
We’re going to take a look at the new Android Studio and see if this can aid in overcoming the gotchas in our build process.