Android CI Setup
Overview
This is documentation on how the Android continuous integration is setup. The purpose of this is to keep a record of our specific setup and as a guide to debugging problems when things are broken. It provides a nice guide to setting up CI for new android projects. Note that references to secrets can be found in either Lastpass or in the android-certificates repo.
Repositories
These are the repositories that were created during the CI setup. Travis treats public and private repos differently so both types were created to test builds on Travis.
- android-certificates - repository that contains all the shared keystore and keys for Sage android projects.
- CardiorespiratoryFitness-Android - uses certificates from android-certificates repo.
- BloodPressureApp - uses certificates from android-certificates repo.
- sandboxpriv - a private sandbox repository for testing. Test projects are in branches. A good project to use as a template is in the dummydroid branch.
- sandboxpub - a public sandbox repository for testing.
Requirements
These are some of the tools required to setup this CI. You will need to install these.
- Fastlane (install with gem not brew)
- Travis client
- Amazon aws client
- openssl
- ruby
- git-crypt
Setup App Keys
The Sage-Bionetworks/android-certificates repo has the keystore and keys for android apps. The files in that repo are encrypted with git-crypt. You'll need to unlock the repo to be able to access the keystore and keys. You can unlock it with either your GPG key or with the master KEYFILE. It is preferable to setup and use your own GPG key, however if you don't have that setup then you can get the KEYFILE from our Lastpass vault, search for "android-certificates". Look for secrets (KEYSTORE_PASSWORD and KEY_PASSWORD) in the SageBionetworks.secrets file.
Once the repo is unlocked you can use the Java keytool to list the keys:
keytool -list -v -keystore SageBionetworks.keystore -storepass "$KEYSTORE_PASSWORD"
If you are setting up a new app then you should add a key for that app to Sage-Bionetworks.keystore. You can do that in Android Studio or using the keytool.
To add a new key to an existing keystore:
keytool -genkeypair -v -keystore SageBionetworks.keystore -storepass "$KEYSTORE_PASSWORD" -alias $KEY_ALIAS -keypass "$KEY_PASSWORD" -keyalg RSA -sigalg SHA256withRSA -validity 9125 What is your first and last name? [Unknown]: Sage Bionetworks What is the name of your organizational unit? [Unknown]: Engineering What is the name of your organization? [Unknown]: Technology Platforms & Services What is the name of your City or Locality? [Unknown]: Seattle What is the name of your State or Province? [Unknown]: WA What is the two-letter country code for this unit? [Unknown]: US Is CN=Sage Bionetworks, OU=Engineering, O=Technology Platforms & Services, L=Seattle, ST=WA, C=US correct? [no]: yes Generating 2,048 bit RSA key pair and self-signed certificate (SHA256withRSA) with a validity of 9125 days for: CN=Sage Bionetworks, OU=Engineering, O=Technology Platforms & Services, L=Seattle, ST=WA, C=US [Storing SageBionetworks.keystore]
Now you can use the new key to "Generate a signed Apk" in android studio. Please enable both "V1 Jar Signature" and "V2 Full Apk Signature" when generating the signed Apk.
Setup Travis
Setting up travis to build and deploy the app to the google play store requires a few steps.
git-crypt
Get the git-crypt.key for android-certificates from our Lastpass account
Travis encrypt the git-crypt.key
travis login --pro travis encrypt-file git-crypt.key --repo Sage-Bionetworks/BloodPressureApp-Android --api-endpoint https://api.travis-ci.com/
The above command should generate a git-crypt.key.enc file and added a travis environment variables to the travis build settings for that project.
Rename git-crypt.key.enc to something more descriptive, like git-crypt-android-certificates.key.enc
Commit the encrypted key file, git-crypt-android-certificates.key.enc (*NOT* git-crypt.key) to the repo.
Delete the git-crypt.key file.
Travis ENV
Set the following travis build environment variables:
CI_USER_TOKEN (from lastpass) - used to allow cloning the android-certificates repo (private repo) KEY_ALIAS (in Sage-Bionetworks.secret) - The app alias KEY_PASSWORD (in Sage-Bionetworks.secret) - The app alias password KEYSTORE_PASSWORD (in Sage-Bionetworks.secret) - The keystore password
Travis SSH Key
Part of the deployment process is to commit a tag to the git repo. In order for travis to do that a SSH key will need to be setup on travis. I typically just upload the travis user "tcisagebio" ssh key which can be found in lastpass. Copy/Paste the private key to a "id_travis_rsa" file and do the following:
# from https://github.com/travis-ci/travis-ci/issues/8680 # In your local terminal > cd path/to/your/local/gitrepo # login by your account --pro or --org > travis login --pro # add the ssh key to travis > travis sshkey --upload id_travis_rsa --repo Sage-Bionetworks/BloodPressureApp-Android --description travis
Workflow
The general workflow is to create stable branches for releases to google play console. Master is used as the development branch and stable-x branches are used for releases. These are the actions when a PR or commit occurs:
pre-merge (or PRs): build and run tests only
post-merge to master: generate an `enterprise` archive build and deploy to s3 bucket
post-merge to stable-x branch: bump build #, generate an `app-store` archive build, deploy to testflight, commit the new build number to the branch. The build then may get promoted to the appstore.
Deployment
Before travis can automatically deploy to google play console you must manually add/create the app. You will also need to add the required images for your app and set the privacy policy. Once you have your app setup on the google play console travis can deploy new builds as updates.
Debugging
This is a collection of issues I ran into and wanted to keep track of. This info may help in debugging problems with integration of android studio, fastlane, google play and travis.
Google Api Error: multiApkDowngradedDevice: Devices with version 4 of this app would be downgraded to version 1 if they met the following criteria: [(API_LEVEL in range 19-0 AND RELEASE_TRACK containing any of each of [[ALPHA]] AND SCREENS containing any of each of [[small, normal, large, xlarge]] AND NATIVE_PLATFORM containing any of each of [[x86, armeabi-v7a, armeabi]] AND FEATURES containing all of [android.hardware.screen.PORTRAIT, android.hardware.FAKETOUCH, android.hardware.LOCATION, android.hardware.CAMERA])].
This indicated that fastlane was attempting to deploy with version 1. In my case, the increment_version_code_plugin was finding versionCode
in the comment and incorrectly setting the next versionCode
Google Api Error: applicationNotFound: No application was found for the given package name
This error means Google api does not allow the first deployment of the app to google play console. The workaround is to manually deploy your app then let travis deploy afterwards. The difference is that travis is updating instead of creating the app on play console.
References: https://github.com/fastlane/fastlane/issues/10324, https://github.com/fastlane/fastlane/issues/3628
Related articles