After developing React Native applications for over 2 and a half years, I found a few paint points when developing, testing and releasing apps in a way that I could fully get my head around and keep my sanity, things like provisioning profiles and staging/production API URLs would cloud my vision. But I finally found an elegant solution.
The model I'm going to explain worked well for me and my team but YMMV.
Pain point 1
In an app stack with a staging
and production
environment, you need to change your API endpoint when developing for TestFlight or the App Store.
For example
https://api.staging.my-app.com
https://api.production.my-app.com
Now back in the day, I would simply merge develop
into master
and then bump the version on master
and also update the API endpoint manually. This is awful.
Solution
The solution was simple, I had a config file which included my endpoint:
// app/config/index.js
module.exports = {
apiUrl: 'https://api.staging.myapp.com/graphql', // default to staging
versionNumber: '1.0.0',
};
Then I created a node script that will change the apiUrl
depending on which arguments I pass to it.
// changeAppConfig.js
module.exports = async (env) => {
await findAndReplace(
config,
/(apiUrl: 'https:\/\/)(.+)(.myapp.com\/graphql',)/,
`$1${env}$3`,
)
};
Note:
findAndReplace
is just a function that takes a file, a regex, and a string which is the replacement using regex grouping. Here is a gist
Now I have a switch.js
module which can take an argument of production
. e.g. $ node switch production
// switch.js
const env = process.argv[2]
changeAppConfig(env)
I would now have a config file which is set to production:
// app/config/index.js
module.exports = {
apiUrl: 'https://api.production.myapp.com/graphql', // changed to production
versionNumber: '1.0.0',
};
So far so good, I can now easily switch between staging
and production
URLs. I can also utilize this within AppCenter by passing an appcenter-pre-build.sh
script.
These run before your app is built and you can pass in environment variables in the build configuration on AppCenter. Here's an example:
#!/usr/bin/env bash
# APP_ENV would be staging or production.
yarn switch $APP_ENV
Great! So now I can have 4 different apps on AppCenter with their environment variables set and the branches configured to build on push.
- iOS staging
- iOS Production
- Android Staging
- Android Production
Using git and releasing to staging/production.
So now I can easily switch between staging and production URLs. Let's talk about how we actually release the apps using AppCenter so QA can test the staging branch and master and build and release to production.
The flow
Our git flow was an adaption from the successful Git branching model with a few small tweaks.
I still use feature branches that are then merged into develop.
After I've got a few PR's merged into the develop
branch, I would then create a staging release.
Now the way I've done this is as follows:
- Branch off of
develop
into arelease
branch with a version number and release candidate number. I try and keep in line with semver.
For this example, let's say it's a minor release, so we will increment the version number from 1.0.0
to 1.1.0
. And it's the first release candidate to staging, so our branch will be release/1.1.0-rc.0
Now this works wonderfully. I can create a staging
release candidate which will now build on AppCenter using the staging
branch, which can now be reviewed by QA and features & develop branches can continue to be worked on.
If I add more features to dev, I can repeat the process and create a release/1.1.0-rc.1
, release/1.1.0-rc.2
and so on.
Note:
release
branches should be deleted after they've been merged.
Releasing to master
Creating a release to master is similar to staging, but you simply merge the release branch into develop and into master, it is a full release, not an RC release, so we omit the -rc.x
value.
Note: RC releases cannot be released to TestFlight, the value
x.x.x-rc.x
is not compatible.
In my next post, I'll explain how I automate version bumps, branches, and pull requests to make deploying a whole lot easier.
How do you currently deploy your React Native applications? What are your pain points and achievements?
Top comments (0)