Problem
You need to update your app's version to 1.0.0:
1. You open up android/app/build.gradle
to update the version and bump the build number.
2. You do the same thing for iOS using Xcode because editing build configuration files directly is more error prone.
3. You need to keep it all consistent, so you open up package.json
and update the version so the reference to the version shown to the user from the JS side is correct.
import { version } from "./package.json"
console.log(version)
// 1.0.0
I feel so productive and happy!
Said no developer ever after going through that.
Solution
The ideal experience is to update only a single version number. Here's what we're going to do:
1. Use npm version [patch|minor|major]
to handle the JS package version (see semantic versioning).
The JS version is our source of truth. Therefore, the Android and iOS versions should match whatever the package.json
version is set to.
2. Use fastlane to handle the Android and iOS sides.
fastlane is an amazing open source tool focused at automating Android and iOS tasks. It has a wide library of community developed plugins that can help us handle things like, versioning.
3. Combine the above 2 steps into a single npm script.
Steps
We will use a fresh React Native project as a starting point:
npx react-native init MyApp
Install fastlane if you do not already have it:
# Install the latest Xcode command line tools
xcode-select --install
# Install fastlane using RubyGems
sudo gem install fastlane -NV
# Alternatively using Homebrew
brew install fastlane
Set up a fastlane directory and create an empty fastfile:
cd MyApp
mkdir fastlane && cd fastlane
touch Fastfile
We want to be able to run the fastlane
command from the root of our React Native project. Therefore we will install our versioning plugins from the root directory:
cd ..
# Install plugins
fastlane add_plugin increment_version_name increment_version_code load_json
Say 'yes' if it asks about creating a gemfile.
The first two plugins are for handling the version, version code on android and the third one is for reading a JSON file (our package.json
).
Next, we are going to add our fastlane scripts. Copy the following to the fastfile at fastlane/Fastfile
.
desc 'Android: Increment versionCode and set versionName to package.json version.'
package = load_json(json_path: "./package.json")
private_lane :inc_ver_and do
increment_version_code(
gradle_file_path: "./android/app/build.gradle",
)
increment_version_name(
gradle_file_path: "./android/app/build.gradle",
version_name: package['version']
)
end
desc 'iOS: Increment build number and set the version to package.json version.'
private_lane :inc_ver_ios do
package = load_json(json_path: "./package.json")
increment_build_number(
xcodeproj: './ios/' + package['name'] + '.xcodeproj'
)
increment_version_number(
xcodeproj: './ios/' + package['name'] + '.xcodeproj',
version_number: package['version']
)
end
desc 'Bump build numbers, and set the version to match the pacakage.json version.'
lane :bump do
inc_ver_ios
inc_ver_and
end
Next we are going to add the following scripts to our package.json for automatic patch, minor and major version bumps:
{
"name": "MyApp",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest",
"lint": "eslint .",
"bump-patch": "npm version patch --no-git-tag-version && bundle exec fastlane bump",
"bump-minor": "npm version minor --no-git-tag-version && bundle exec fastlane bump",
"bump-major": "npm version major --no-git-tag-version && bundle exec fastlane bump",
},
The first part of the command will upate the JS package version without making a commit to the git repo. The second part will execute the fastlane bump command, which will automatically bump the android and iOS build numbers and update the version to match the JS side.
# npm
npm run bump-patch
# yarn
yarn bump-patch
PS: I'm maintaining a React Native template with a lot of goodies like the one in the article.
Top comments (17)
Thank you: this helped me a lot in a project few months ago!
SOLVED ISSUE
I started a new react-native project with updated versions of softwares, and I faced following issue. When I execute:
I get this error:
Googling a bit I found this: github.com/fastlane/fastlane/issue...
And effectively I have (now, for this project) ruby 3.0, not 2.6.5 anymore (I thinked was something related to upgrated OS from Mojave to Catalina, or to new Node.js...)
So I 'solved' by downgrading ruby to 2.7.2 and now it works like a charm again!
Added too auto-changelog
and add to package.json script
thats will be automate create changelog after automate versioning
Can't you use
package['name']
in Fastline file? What is the reason chosingENV[APP_NAME]
over it?Good point! Thanks. I've updated the post!
The reason being is that I copied most of the fastfile for this post from a project I was working on where
pacakge['name']
was different from the Xcode project name ๐Very good, one issue I noticed as I currently only have Andorid not iOS and because the iOS function runs in Fastlane first it errors and stops the following Android function firing. I've modified it so that both functions run independently so that now if one fails the other still tries. Hope its helpful to anyone else using only one OS.
What a coincidence, that is exactly what I was looking for and you just published it! Thx :)
Happy it helped!
Thank you very much for this wonderful guide.๐๐พ๐
This is great! I was using app.json for that. If I use your solution, do I need to remove the buildnumber and versioncode from app.json? Thanks!
No strict rules here! The solution is customizable! Do what suits your needs and makes more sense to you ๐
Great Work , If possible please do write on fastlane setup for react native.
Thank you:)
I do have another guide. I hope you find it useful:
github.com/osamaq/reactnative-fast...
Really Thank you so much.
This will have issue with xcode 11 as there is new variable need to use github.com/SiarheiFedartsou/fastla...
Hi @osamaq ! I'll try this, it would be very useful. Thanks!
Do you know if it'll work exactly with Xcode 12? Thanks again.
It does. I've used it many times while working with Xcode 12.0.1. have fun ๐