Releasing a React Native application
About 9 months ago, Tanda started working on a new app to improve the way that employees interact with their company. We decided to roll out the app with the help of React Native.
A big challenge when starting out was how to architect the application to ensure minimal impact of bad code to customers, speedy deploys and stability.
Tanda has always focussed on the web, where deploying is easy, and after fixing a bug, a user just has to refresh the page. Mobile is a different story. Bad code can render the app un-bootable, and the only option to get a fix is to re-install from the app/play store. What’s worse is that Apple, at least, can take a fair while to approve your update. This results in the support team getting bombarded with calls/chats asking for help and the only thing that will help is time.
That being said, we didn’t want to lose all the benefits we’ve come to love from the web, so getting code out nice and fast was a big priority.
We decided on CodePush to handle that. CodePush is a service by Microsoft that holds your JavaScript bundle (for react-native or cordova) and sends it down to your application. This allows us to update the code in the app on the fly, without needing to go through the app approval process. It doesn’t come without problems, however. It only works for JavaScript-only changes. If you add a new native package, or change any native code, CodePush can’t distribute that, and you’ll need to go through the app store. The biggest problem, though, is that your app can still get stuck in a state where it can’t boot the bundle.
To help with this, we decided on three build pipelines, dogfood (known to most as internal), nightly and release, to thoroughly check all new code before it reaches customers
Dogfood gets every commit that gets merged into master
. All Tanda employees are encouraged to use this Internal version of the app, to test new features and catch any bugs that may make it in. Native versions are distributed on Apple using TestFlight (which still takes a while to approve, but is sometimes instant…?). Android uses the ‘Alpha’ lane to distribute this to a closed-off Google Plus community with everyone from Tanda in it. For non-native changes, as soon as a pull request is merged, the Dogfood version will get an update.
The nightly version is built from a branch called nightly
. This branch is set to the current head of dogfood
every morning at 3am. We don’t use this build as much as we should, but it does exist.
To get code into release, our bot automatically generates a ‘release candidate’ using Zapier and a small Lambda. It creates a new branch at ~4am on a Thursday morning that is at the same point as nightly
— the release candidate is the same as Dogfood on Wednesday afternoon. This is our ‘cut-off’ for new code. Past this point, any more changes won’t make it to the end user before the next release candidate.
We use a hotfix system to make amendments to the code in the release candidate, and we have our QA team go through the whole application (it’s still quite small) to check that there is nothing broken by this release.
On Tuesday morning at ~7am, Tanda Panda checks to ensure that we have review approvals from QA, and then merges the candidate into the Release branch. Automated deploys push this to all our users.
If there were any changes, made to the release candidate, we merge the Release branch back into the Dogfood branch to bring all bug fixes up-to-date.
So, that’s how we solve the mobile release problem. We make sure we find the right balance of getting code onto devices easily (using CodePush), but with the necessary checks in place (pull request reviews and quality assurance) to make sure we don’t release bad code. This keeps developers happy, and the support team happy.
Got any tips or tricks you use to handle similar situations? Let me know about them. I’m always curious as to how I can improve our build process.
Want to learn more about Tanda and how we work? Come along to our hackathon!