Skip to content
Logo Theodo

Build the React Native Deployment Pipeline of Your Dreams in 1 Hour with Fastlane, Circleci, Codepush and Appcenter.

Félix Mézière15 min read

How is this tutorial different?

It’s a modus operandi.

This tutorial will make your React Native deployment pipeline completely operational in 1 hour for iOS and Android.
Other tutorials do a general presentation that lets you figure out the details or a zoom-in on a particular part of the pipeline or a deep-dive on every component which would take too much time to read and require you to join the bits together to make the deployment pipeline.
You can find such articles with this Google search.

In this tutorial, you won’t have to open Xcode nor Android Studio, not even once.

It is based on a generator

In this tutorial, you will make heavy use of the awesome generator-rn-toolbox. Thanks @Theodo and @BAM ;)
This will maximise setup speed, reduce bug surface and ensure up-to-date standards when you create your deployment pipeline.

It is designed to be run on existing project (whether it’s a 3 years old project or a fresh react-native init awesomeProject doesn’t matter)

The resulting deployment pipeline is super customisable

There isn’t too much magic. After this, you will have a skeleton with the time-consuming essentials setup but which is very easy to:

What if you don’t understand the moving parts of this deployment pipeline (e.g. the infamous Apple code signing) or its day-to-day workflow?

Get more insights with our in-house detailed docs on how this works here. This is quite opinionated to fit our needs though.
If you still don’t understand something, Google that part specifically until you feel confident, then come back here :-)

This React Native deployment pipeline is meant for you to customise: it is a way for you to learn how all the tools can work together. I expect you to get your hands dirty after setting it up to tweak it to your exact needs.

The stack

Why a CI server instead of VS AppCenter for builds?

Among other problems, Appcenter Build is slow, not very customisable and doesn’t handle state-of-the-art shared code signing with match.
One of its biggest issues is also that it’s hard to debug: the build tools and scripts used are different than the ones used to build locally and it’s not possible to ssh into the distant build machine.
We love Appcenter Releases and CodePush though, that’s what we’ll use here for deployment hosting!

At Theodo, we chose CircleCI because it’s performant, widely used accross web and mobile (which makes sense since React Native devs often come from the ranks of Web devs) and is very customisable. Lots of CI tools are compatible with Fastlane so feel free to swap this one.

Workflow that you will get once completing this

Prerequisites

Steps

⚠️ FRIENDLY ADVICE
Remember to commit after each step

1. Create the staging apps in Appcenter

(We create different apps for staging and prod in appcenter mainly because appcenter analytics + crash reports are per-app).

2. Setup Fastlane

npm install --global yo
gem install bundler
yarn global add appcenter-cli generator-rn-toolbox
appcenter login
yo rn-toolbox:fastlane-setup
# First commit

Answers

3. Create staging environment

yo rn-toolbox:fastlane-env
# Second Commit

Answers

4. Create iOS staging deployment certificates and profiles

This creates all the certificates and profiles required for your app in the Apple Dev Portal and installs them in your local environment.

bundle exec fastlane ios setup --env=staging

You will be asked twice for a match passphrase for the repo. If you are using an existing match repository, ask for the passhphrase, otherwise define it here and note it somewhere: this is the password to share with teammates so that they can get the iOS code signing identities (you shouldn’t need this if you setup automatic React Native deployment with CircleCI, in which case you will enter the match passphrase once in the CI server).

5. (If needed) Open src/environment/index.staging.js and update it with all required js environment variables for the staging environment. Commit.

6. Wrap your app with CodePush

In order for CodePush to work, it needs to wrap your app as explained here​.

import codePush from "react-native-code-push";
import { AppRegistry } from "react-native";
import { ENV } from "./src/environment";
import AppContainer from "./App";​

// Below is an example of how CodePush behaviour can be made different in production: in this case, update will be installed to prod devices only after user has stopped using it for 2 minutes.

const codePushOptions = {
  checkFrequency: codePush.CheckFrequency.ON_APP_RESUME,
  installMode: codePush.InstallMode.ON_NEXT_SUSPEND,
  minimumBackgroundDuration: ENV === "production" ? 120 : 0
};​

const CodePushedApp = codePush(codePushOptions)(AppContainer);
AppRegistry.registerComponent("yourApp", () => CodePushedApp);
// Third Commit

7. Pack the Staging secrets in an encrypted archive

yarn pack-secrets -e staging
# Fourth Commit

⚠️ Make sure that you commit the resulting archive and note down the passphrase somewhere

This archive contains all the staging env secret passwords and files. If you lose it, you won’t be able to deploy the app anymore. This archive is useful to share the secrets between developers without having to send through email/usb etc.

⚠️ In the future, whenever adding more secret files (e.g. Firebase keys), make sure that you run the following steps:

It would be cool to replace this encrypted archive with the use of transcrypt, PRs welcome! :)

8. Hard-Deploy Staging

yarn deploy -t hard -e staging

=> You can now download the staging app on your phone at https://install.appcenter.ms

9. Soft-Deploy Staging (CodePush)

yarn deploy -e staging

=> You should receive the update you CodePushed directly on your phone without having to manually update your app from Appcenter.

10. Create production environment

yo rn-toolbox:fastlane-env
# Sixth Commit

Answers

11. Setup iOS production deployment certificates

bundle exec fastlane ios setup --env=production

12. Pack the Production secrets in a encrypted archive

yarn pack-secrets -e production
# Sixth Commit

⚠️ Make sure that you commit the resulting archive and note down the passphrase somewhere. Passphrase should be different than for staging to allow different access rights.

This archive contains all the production env secret passwords and files. If you lose it, you won’t be able to deploy the app anymore.

⚠️ In the future, whenever adding more secret files (e.g. Firebase keys), make sure that you run the same steps as for staging above (replace staging with production)

⚠️ If you lose the keystore file present in this archive, you will not be able to deploy the Android app ever again and will have to create a new app in the Google Play Store.

13. (If needed) Open src/environment/index.production.js and update it with all required js environment variables for the production environment. Commit.

14. Create the production apps in the portals

  yarn deploy -t hard -e production -o android

15. Make sure you have an app icon

Otherwise AppStore Connect will not accept your app. You need a 192 x 192 png.
Thanks generator-rn-toolbox again! :)

yo rn-toolbox:assets --icon relative/path/to/your/icon.png
# Seventh Commit

16. Hard-Deploy Production

yarn deploy -t hard -e production


=> You should now be able to see your app’s binaries in both Google Play Store Internal track (“add from library”) and AppStore Connect’s TestFlight.

17. Soft-Deploy Production (CodePush)

yarn deploy -e production

=> You should receive the update you CodePushed directly on your phone without having to update their app.

18. Now setup automated React Native deployment with CircleCI so that no-one has to use these commands anymore :)

Appendix: Some nice tweaks to do, good exercises for you to understand the moving parts of the stack

If you want to know more about the why of all this, checkout this video of my talk at the React Native London Meetup!

Liked this article?