A Simple Continuous Deployment of a React Native App to Google Play

We will create a simple Github Action to build and deploy a React Native mobile application automatically upon pushing to a specific branch.

Image for post
Image for post
Photo by Kelvin Ang on Unsplash

Pre-Requisites

Prepare for Secret Injection

To ensure authenticity, an uploaded application needs to be signed via an upload certificate that is password protected. In order to securely provide this password to our application at compile time we need to define it in our build configuration.

Edit the release certificate configuration in android/app/build.gradle by adding the following code block inside signingConfigs:

release {
storeFile file('upload-key.keystore')
storePassword MYAPP_UPLOAD_STORE_PASSWORD
keyAlias 'bigdelivery-sales-app-upload-key'
keyPassword MYAPP_UPLOAD_KEY_PASSWORD
}

Then edit the line signingConfig signingConfigs.debug to signingConfig signingConfigs.release in buildTypes → release. These changes will allow us to inject the password for the upload key at build time.

Configure Fastlane

To ease integration with Google Play upload APIs we will be using Fastlane to build and upload our application. Fastlane needs to be configured locally before running it in our CI. For installation instructions on your local machine see here. To configure Fastlane, run fastlane init from inside the android application directory and follow the on-screen instructions. When asked for the location of the JSON key file enter api.json.

Edit the android/fastlane/Fastfile to include a deploy lane as shown below:

default_platform(:android)platform :android do
desc "Deploy a new version to the Google Play - Alpha"
lane :deploy_alpha do
gradle(task: "clean bundleRelease -PMYAPP_UPLOAD_STORE_PASSWORD=#{ENV['STORE_PASSWORD']} -PMYAPP_UPLOAD_KEY_PASSWORD=#{ENV['KEY_PASSWORD']}")
upload_to_play_store(track: 'alpha')
end
end

The -P flag is used to inject our runtime configuration as explained here. Note that these variables correspond to the passwords we setup in the previous section.

Saving Secrets

The JSON api key, the keystore containing the upload key and associated password should not be committed to GIT or otherwise exposed. Therefore, we will be creating the following secret variables using Github Secrets:

To base64 encode the upload key and service account use the command: cat fileToEncode.extension | base64 on your local machine.

The Action

Github Actions provide a way to transparently run deployment, testing and other workflows directly from within Github without having to configure or maintain infrastructure. These actions are fully defined using YAML files.

The full action can be seen in the code block below. It consists of the following steps:

name: Deploy Android
on:
push:
branches:
- master
jobs:
deploy-android:
runs-on: ubuntu-18.04
steps:
- name: Checkout Repository
uses: actions/checkout@v2

- name: Get Upload Key
working-directory: ./android/app
run: echo ${{ secrets.UPLOAD_KEY }} | base64 -d >> upload-key.keystore

- name: Get Service Account Config
working-directory: ./android
run: echo ${{ secrets.SERVICE_ACCOUNT_JSON }} | base64 -d >> api.json

- name: Install Packages
run: yarn --frozen-lockfile

- name: OPTIONAL Jetify
run: npx jetify
- name: Compile and Upload
uses: maierj/fastlane-action@v1.4.0
with:
lane: "deploy_alpha"
subdirectory: "android"
env:
MYAPP_UPLOAD_STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
MYAPP_UPLOAD_KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
LC_ALL: en_US.UTF-8
LANG: en_US.UTF-8

Conclusion

Following the above steps you should be able to programmatically deploy the Android version of a React Native mobile application to the Google Play Store without human intervention.

The current setup deploys to the closed Alpha track where you can have a designated developer responsible for promoting it into a full release. However, you can change that to what works best with your organization’s release flow!

Written by

A curious minded engineer.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store