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.

Pre-Requisites
- A react-native application that builds successfully.
- An active Google Play account with the desired app already deployed (Google does not allow the first deploy to be programatic).
- A JSON key file for a service account user with access to the Google Play APIs. See how to create one here. Renamed to
api.json
and placed inside theandroid
directory. - A valid App upload key. See how to create one here.
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:
- STORE_PASSWORD → keystore password
- KEY_PASSWORD → key password
- UPLOAD_KEY → Base64 encoded upload keystore
- SERVICE_ACCOUNT_JSON → Base64 encoded service account API key
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:
- Clones the repository
- Retrieves the keys, base64 decodes them and dumps them to their respective files that can be accessed by later steps
- Installs all NPM packages
- Jetifi’s the application modules. This may be required if some of your dependencies are not yet AndroidX capable.
- Compiles and uploads the application using Fastlane!
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!