We are playing since a few weeks with React Native for a Proof Of Concept and wanted to have the same development workflow for mobile apps, as we have for the web.
Here is the workflow we use for web development:
- Branch : every bugfix or feature is developed on a new git branch,
- Pull Request (PR) : we make PR for each bugfix or feature to propose the modification to the « master » git branch,
- Code Review : other teammates have to review each PR and add :+1: when they agree with the modification,
- Test : a CI system (Jenkins) runs Unit and Integration tests, and Lint on each PR,
- Preview : an internal tool (Github Hooker) is called with a Github webhook on each PR to create a staging environment.
When every step is ok, the PR is merged.
The « Branch step », « PR step » and « Code Review step » are mostly related to our CVS (Github Enterprise) and are not a problem. The « Test step » is related to React Native. We already use Jest and ESLint, but we have to dig more for Integration test (Appium ?).
The « Preview step » is more interesting. It was not the simplest thing to do on our web project, but this is probably one of the most useful feature we have on our stack. Having a staging environment for all open PR allows devs, PO, PM and scrum masters to play with this exact version of the code (on any browser they want), and really see if the bug is fixed, or if the feature correspond to the PO needs. It allows everyone to iterate and make feedbacks before the code lands on the master branch. It’s also a good way to be sure your app build didn’t fail.
So, what we want is to have on each of our React Native PR, a link to preview iOS and Android version of our app in a web browser, refreshed after every commit on the branch.
The goal of this blog post is just to show you, that it is something doable and really useful. If you are interested in, here are some more information, that maybe can help you.
Concerning the CI, we already use Jenkins, so we will continue to. Beware that for building iOS apps, a CI running on OSX is needed. In our case, we had added a Jenkins slave to our Jenkins pool. If you don’t have CI system internally, you should take a look at Bitrise or CircleCi because they propose OSX CI systems. Our CVS is Github Enterprise, but everything is also possible with Gitlab (or any other CVS). We use Fastlane.tools to automate build and credentials support. (Mostly because it was recommended by some of our iOS developers).
In order to preview iOS and Android app in a web browser, we use the amazing SAAS service Appetize.io (free for 100min/month).
How did we do ?
We had set up an OSX machine with a fresh Jenkins install, and created a job that triggers a build everytime a push is made on a PR, thanks to the “Github Pull Request Builder » Jenkins plugin. There is also a lot of things to configure on this machine (Nodejs, Ruby, xCode …), and i recommend you to do some builds (iOS and Android) manually to be sure everything is ready.
Fastlane is an open-source automation toolset for iOS & Android. It lets you write « lane » to automate a lot of things. We set up a unique Fastlane file at the root of our React Native project directory dealing with Android & iOS lanes.
To suit our needs, we created one lane « deployAppetize » for each platform: it performs the corresponding build, uploads it to Appetize.io via their API, and updates the Github PR Statuses during the process.
I’m not a Ruby programmer, so please, don’t blame me, and feel free to improve the code below if you want (on this Github Gist). This is neither the state of the art, nor a beautiful open source thing, we just share what we did in case it helps someone :-)
Before doing anything, you’ll have to set some variables on Fastlane, so go to the
Fastfile file in your
Create a private lane to make the POST request to your Github statuses API to avoid DRY:
Appetize allows you to create different apps. We want one app per PR, and update the corresponding app when a new commit is made on a PR. For that, we keep track of the branch name by storing it in the « notes » field of the app on Appetize.io.
So, here’s a private lane to get back the public key of the corresponding app on Appetize.io, to update the good one if it already exists.
Now, we have everything ready to do the deployAppetize lane for iOS :
For Android, it’s almost the same things, except we have to do some small business logic to find the apk generated by
Gradle, with this private lane :
And now you should be able to also deploy to Appetize.io on Android :
It’s over. You just have to add those commands to your CI to do the job :
npm install Fastlane ios deployAppetize Fastlane android deployAppetize
You have now two new checks on each PR with a link to the iOS or Android instance on Appetize.io.
Fastfile on a Github Gist : FastFile
At M6web, we are glad to see the whole React Native promise taking a concrete shape: the developer experience is the same for both mobile & web development, even about tooling. We are continuing to play with it and we’ll certainly keep posting articles here, stay tuned !
P.S.2: You could also look at Reploy.io, which try to improve this workflow with extra features and a more cleaner UX than Appetize.io, but it is “alpha” for now.