Securely signing our Android builds in our Jenkins CI (Continuous Integration) environment is a common problem here at Detroit Labs. There are a few different options we’ve tried over time, and each felt a little dirty…except one.
First, a little background: Continuous integration is a very valuable tool for a development team to leverage. When used correctly and frequently, it can dramatically reduce the time spent debugging and fixing conflicts. Problems are visible to the entire team and can be addressed quickly, build output can help identify the root cause, and unit tests can help prevent the introduction of regression. It can also automate deployments so your QA team or clients get their hands on the latest and greatest frequently.
Here are our options…
Include the signing certificate for your build in the repository itself: BAD!
Unless you are using a private source control system, you are essentially publishing your signing certificate for the entire world to see. Even if you are on a private system, you are placing the cert on every developer’s machine, which increases your chances of it becoming public.
Upload the signing certificate to the Jenkins file system and reference from the Gradle file: OK…
This is OK because it keeps the cert in a minimal number of locations and should be secured behind your Jenkins security. One sticking point is you will still need to store the passwords and alias somewhere on the filesystem. Finding a way to do this securely can be challenging. This solution also becomes difficult to manage if you have multiple projects and multiple build slaves that will each need a cert
Using the Jenkins Android Signing Plugin: GREAT!
This is a great, clean solution for storing and signing applications on your Jenkins system. The plugin uses the standard Jenkins credentials storage for handling your certificates. This limits the number of developers who need to know the passwords, handles securely storing the certs and passwords, and allows all build slaves access to the certificate.
How to configure and use the Jenkins Android Signing Plugin
First, you will need to make sure you have the Credentials Plugin installed on your Jenkins system. You can check this by taking a look at the left side of your Jenkins installation. If you see the “Credentials” link as shown below, you have it installed.
If you do not have the “Credentials” section, you will need to install it. You can do this at the same time as the signing plugin.
To do this follow these steps:
1. Select the “Manage Jenkins” section as shown below.
2.Select “Manage Plugins.”
3.You should be able to see updates for your current plugins. At the top of the screen select the “Available” tab.
4.You can now use the search box in the upper right to search for “Credentials Plugin” (if you do not have it installed) as well as “Android Signing Plugin.” Check the boxes on the left side of each item, then select “Download now and install after restart” at the bottom of the screen.
Great!
Now that you have everything installed, you will need to add at least one certificate to be used for signing applications. The detailed instructions on using the Jenkins Credentials Plugin are out of scope for this article but can be found online. You will need to add a new credential of type “Certificate” as shown below.
As you can see, the plugin only supports a “PKCS12” certificate. Unfortunately, the more recent versions of Android Studio output a certificate as a “JKS” certificate, which is incompatible. Thankfully, the handy “keytool” command line utility can convert our “JKS” file to a “PKCS12” format using the following command.
keytool -importkeystore -srckeystore {REPLACE_WITH_JKS_FILE} -srcstoretype JKS -deststoretype PKCS12 -destkeystore ConvertedCertificate.p12
Once you have your “PKCS12” file, you can upload the certificate. Make sure to enter the password before uploading or the upload will report a failure. Now you are ready to use this certificate on any of your Android jobs.
The only requirement for the source code itself is that you leave the “signingConfig” definition empty for the “buildType” you would like to sign with Jenkins. This will create an unsigned APK that can then be signed using the plugin. Note: the standard debug build type is automatically signed with your debug certificate.
Now that everything is set for signing, you need to add the “Sign Android APKs” build step to your Jenkins job. Below is a simple example of first running the Gradle commands to assemble an unsigned release build. After that, you can sign the build using the signing build step. You must select the certificate you would like to use from the credentials storage, specify the alias, and give a path to locate the unsigned APK.
That’s it! You will have a signed build ready to distribute after the build completes.
Any questions? Reach out to me on Twitter.
Note: Google recently announced a new certificate storage option on Google servers, watch for a follow-up post about using this as an alternative signing option.