How to set up APK release CI/CD on Github
Intro
This article documents the process for integration of the android client release process to the CI for automation i.e CI/CD on Github. The repository set up requires admin rights to set up the credentials for the Github Actions CI pipeline.
This set up supports tagging releases on Github as pre-releases if they include alpha or beta keyword in the tag e.g. v2.3.5-alpha
Contents
Gradle Configuration
Github Actions CI
Credentials configuration
Publishing via Tag
Signed Release for APK releases
Gradle configuration
Your applications build configuration should have the various properties configured to sign the release. One can use the alternative configuration with the credentials stored in a keystore.properties
file.
The following gradle configuration combines both system environment variables and keystore properties file approach where the latter is only used if the environment variables are empty
apply from: '../properties.gradle'
signingConfigs {
release {
v1SigningEnabled false
v2SigningEnabled true
keyAlias System.getenv("KEYSTORE_ALIAS")?: project.KEYSTORE_ALIAS
keyPassword System.getenv("KEY_PASSWORD") ?: project.KEY_PASSWORD
storePassword System.getenv("KEYSTORE_PASSWORD") ?: project.KEYSTORE_PASSWORD
storeFile file(System.getProperty("user.home") + "/<project>.keystore.jks")
}
It is recommended to have a separate properties.gradle
file to process the key store properties then import in the above build.gradle
file using apply from: '../properties.gradle'
as shown above.
ext.props = new Properties()
//KEYSTORE CREDENTIALS
def keystoreAuthArray = ["KEYSTORE_ALIAS", "KEY_PASSWORD", "KEYSTORE_PASSWORD"]
if (rootProject.file("keystore.properties").exists()) {
props.load(rootProject.file("keystore.properties").newDataInputStream())
keystoreAuthArray.each { arrayProp -> project.ext.set(arrayProp, props.getProperty(arrayProp, "sample"))
}} else {
println("keystore.properties does not exist. The following values are required " + keystoreAuthArray.join(", "))
keystoreAuthArray.each { arrayProp -> project.ext.set(arrayProp, props.getProperty(arrayProp, "sample_" + arrayProp))
}}
Sample content of keystore.properties file
KEYSTORE_PASSWORD=xxxxxx
KEYSTORE_ALIAS=xxxxxx
KEY_PASSWORD=xxxxxx
NB: When using this approach to store credentials please remember to add a `keystore.properties` entry to the `.gitignore` file to prevent versioning on git
Github Actions CI
You can create a new Github action workflow file and name it release.yml with the following sample configuration used for building, signing and publishing the OpenSRP ZEIR application as a Github release.
NOTE: Remember to update the content with the module names corresponding to your project.
Credentials generation and configuration
Android requires that all release APKs be digitally signed with a certificate before they are installed on a device or updated. This requires that you generated a Keystore. To do this on Android Studio, you can follow the instructions here.
Alternatively if you have the
keytool
utility on your workstation you can generate one using the command`keytool -genkey -v -keystore my_keystore.jks -alias <my_alias_name> -keyalg RSA -keysize 4096 -validity 1000`
When generating the Keystore above you will be prompted to enter the
KEYSTORE_ALIAS, KEYSTORE_PASSWORD, KEY_PASSWORD
. Please note, if your platform doesn't prompt you for a second password when generating the Keystore (e.g. of type PKCS12) then the KEYSTORE_PASSWORD and KEY_PASSWORD values will be the same.You need to then store the above credentials in your repository of choice. The values need to correspond to the exact naming on your Github actions workflow config file. For more on setting up repository secrets see this link.
You need to store the base64 encoded versions of the content of these files:
my_keystore.jks
keystore filelocal.properties
file. (If relevant to your project)keystore.properties
file. (If using Example 2 approach above under Gradle Configuration)
The above base64 content needs to be stored on Github under the corresponding variable names. This name should correspond to what is on the Github Actions workflow config file e.g.
my_keystore.jks
- KEYSTORE_FILElocal.properties
- LOCAL_PROPERTIESkeystore.properties
- KEYSTORE_PROPERTIES (required if using Example 2 approach)google-services.json
- FIREBASE_CONFIG (Do not encode these into Base64)
You can convert to Base64 using the following command that uses the openssl utility
openssl base64 < my_keystore.jks | tr -d '\n' | tee my_keystore_base64_encoded.txt
NB: You need admin rights on the repo to access Settings menu
Publishing via TAG
As part of integrating Continuous Delivery(CD) into the development lifecycle, CI has been set up to trigger release APK generation. The configuration requires the tag to have a prefix in the glob pattern format:
v[0-9]+.[0-9]+.[0-9]+[0-9a-zA-Z.-]+
Thus the following are all valid tags that will trigger the generation of a release APK
v1.4.0
v1.4.0-alpha
v1.4.0-zeir-beta
v1.4.0-anc-rc1
Note: e.g. when creating a tag for the zeir version 1.4.0, use the command:
git tag -a v1.4.0-zeir -s && git push origin v1.4.0-zeir
When you run the command, you will be prompted to add a message. The message should be of the format:
Template | Sample |
---|---|
TITLE | BETA RELEASE |
NOTE: For convention, the TITLE should be Capitalized. The release notes should show to what was updated.
Also please see Semantic versioning
Accessing your releases
Once the above command is executed and the tag is pushed, Github CI triggers an action to build the signed release APK and upload it as part of the tag’s assets.
One can access the published APK under Github’s releases url e.g. for ZEIR
https://github.com/opensrp/opensrp-client-path-zeir
This site is no longer maintained. Please visit docs.opensrp.io for current documentation.