I've often found myself wanting to just assign new build number to my apps. This simple task turns out to be harder that it seems at first. There's a production build number (on App Store and Google Play), you might also have separate build numbers for beta, alpha, and other versions of your app.
Fortunately, all of these services provide fastlane actions to get the latest build number.
Unfortunately, every service provides app's build number in a bit different format, which makes it not-so-straightforward to get the latest-latest version number.
This is my take at automating this.
Supported services:
- App Store (via app_store_build_number)
- TestFlight (via latest_testflight_build_number)
- Google Play (via google_play_track_version_codes)
- Firebase App Distribution (via firebase_app_distribution_get_latest_release)
- App Center (via appcenter_fetch_version_number)
The latest build number is persisted in
$TMPDIR/latest_build_number.txt
, so you can use it across
fastlane
invocations. For example, you could safely do:
$ cd ios && bundle exec fastlane prod && cd ..
$ cd android && bundle exec fastlane prod && cd ..
$ cd symbian && bundle exec fastlane prod && cd .. # lol
The first fastlane
invocation retrieves the latest build number. Then, the 2
subsequent invocations simply reuse the latest build number from the file.
The new build number is derived using this complex forumla:
new_build_number = latest_build_number + 1
Simple use case. This will only take the latest version from Google Play. This
might not seem very useful at first, but is is when you have different version
codes for different tracks (production
, beta
, alpha
, internal
).
Let's say that your Play Console looks like this:
production
is at version code60
beta
is at version code61
alpha
is at 2 version codes:64
and65
(becasue you're doing some fancy testing)
In this case, get_new_build_number
action would return 66
(because it is
newer/higher/bigger than all the other build numbers).
# android/fastlane/Fastfile
default_platform(:android)
platform :android do
desc "Deploy a new beta version to Google Play"
lane :beta do
build_number = get_new_build_number(
package_name: ENV["APP_PACKAGE_NAME"], # e.g com.example.yourapp
google_play_json_key_path: ENV["GOOGLE_PLAY_JSON_KEY_PATH"], # path to JSON key for authenticating with Google Play Android Developer API
).to_s
build_android_app(
task: "bundleRelease",
project_dir: "..",
properties: {
"android.injected.version.code" => build_number,
},
)
upload_to_play_store(
track: "beta",
aab: "./build/outputs/bundle/release/android-release.aab",
json_key: ENV["GOOGLE_PLAY_JSON_KEY_PATH"],
)
end
end
If you provide more parameters, the plugin will take them into account. For
example, if you pass bundle_identifier
to get_new_build_number
:
platform :android do
desc "Deploy a new beta version to Google Play"
lane :beta do
build_number = get_new_build_number(
bundle_identifier: ENV["APP_BUNDLE_ID"], # e.g com.example.yourApp
package_name: ENV["APP_PACKAGE_NAME"], # e.g com.example.yourapp
google_play_json_key_path: ENV["GOOGLE_PLAY_JSON_KEY_PATH"], # path to JSON key for authenticating with Google Play Android Developer API
).to_s
build_android_app(
task: "bundleRelease",
project_dir: "..",
properties: {
"android.injected.version.code" => build_number,
},
)
upload_to_play_store(
track: "beta",
aab: "./build/outputs/bundle/release/android-release.aab",
json_key: ENV["GOOGLE_PLAY_JSON_KEY_PATH"],
)
end
end
then also build numbers in App Store will be taken into account.
Building on the previous example, let's say that your Play Console looks like this (same as before):
production
is at version code60
beta
is at version code61
alpha
is at 2 version codes:64
and65
(becasue you're doing some fancy testing)
And let's say that you App Store looks like this:
- production is live at version code
81
In this case, get_new_build_number
action would return 82
(because it is
newer/higher/bigger than all the other build numbers). Of course, you have to be
authenticated to App Store using
app_store_connect_api_key.
This makes it easy to keep version codes in sync in your app across different app stores.
Please note that this action is simple and has no protection against concurrent builds. Is is probably unsafe to use in an environment when many releases happen in a short time frame.
This project is a fastlane plugin. To
get started with fastlane-plugin-get_new_build_number
, add it to your project
by running:
fastlane add_plugin get_new_build_number
Retrieves the new build number for your app.
This plugin provides a single action, get_new_build_number
. For now, see
source code to learn how to use it. I might write some docs later.
Check out the example Fastfile
to see how to use this
plugin. Try it by cloning the repo, running fastlane install_plugins
and
bundle exec fastlane test
.
Note to author: Please set up a sample project to make it easy for users to explore what your plugin does. Provide everything that is necessary to try out the plugin in this project (including a sample Xcode/Android project if necessary)
To run both the tests, and code style validation, run
rake
To automatically fix many of the styling issues, use
rubocop -a
For any other issues and feedback about this plugin, please submit it to this repository.
If you have trouble using plugins, check out the Plugins Troubleshooting guide.