Creating Android App always involves tracking its Version Code and Version Name across different Product Flavors and increment these values when shipping new feature into the market this process may be tedious and error prone. This project shows how we can automate this process with the combination of gradle and Fastlane.
An integer used as an internal version number. This number is used only to determine whether one version is more recent than another, with higher numbers indicating more recent versions. This is not the version number shown to users; that number is set by the versionName setting, below.
The value is an integer so that other apps can programmatically evaluate it, for example to check an upgrade or downgrade relationship. we can set the value to any integer we want, however we should make sure that each successive release of our app uses a greater value. The system does not enforce this behavior, but increasing the value with successive releases is normative.
Typically, we would release the first version of our app with versionCode set to 1, then monotonically increase the value with each release, regardless whether the release constitutes a major or minor release. This means that the versionCode value does not necessarily have a strong resemblance to the app release version that is visible to the user (see versionName, below).
Apps and publishing services should not display this version value to users.
Warning: The greatest value Google Play allows for versionCode is 2100000000.
A string used as the version number shown to users. This setting can be specified as a raw string or as a reference to a string resource. The value is a string so that you can describe the app version as a <major>.<minor>.<patch>. string, or as any other type of absolute or relative version identifier. The versionName has no purpose other than to be displayed to users.
For our application we have used versionName as below
<major>.<minor>.<patch>(buildNumber)
1.0.0(14)
A product flavor defines a customized version of the application build by the project. A single project can have different flavors which change the generated application.
Create two version properties files for each Product Flavors. i.e (one for successful incremental task and other for handling error case which will revert all update made to version name and version code.
Update file path in project.ext
as shown in root build.gradle file
VERSION_CODE
andVERSION_MAJOR
should start from 1 by default in success and error version property file.
Example
DevelopmentVersion.properties
VERSION_MAJOR=1
VERSION_MINOR=0
VERSION_PATCH=0
VERSION_CODE=1
VERSION_BUILD=0
DevelopmentErrorVersion.properties
VERSION_MAJOR=1
VERSION_MINOR=0
VERSION_PATCH=0
VERSION_CODE=1
VERSION_BUILD=0
performVersionCodeAndVersionNumberIncrement
gradle task is responsible for version name and version code incremental. It takes two command line parameters i.e. Version Type & Build Variant Type.
This parameter tells which product flavor we need to use for incremental task i.e (Production,Stagging,Qa,Developement)
. In majority of our cases we have up to 4 product flavors or less. For demonstration I have used only three flavors i.e. (Production,Qa,Development
) and these flavors are defined as constant values in build.gradle. Its command line parameter key name is buildVariantType
productionFlavor="production"
qaFlavor="qa"
developmentFlavor="development"
These constant values are used to validate user input given from command line they are case sensitive.
This parameter tells which version to increment i.e (Major,Minor,Patch,Build)
. Its command line parameter key name is versionType
gradlew task -PversionType=development -PbuildVariantType=Build performVersionCodeAndVersionNumberIncrement
Above code snippet will increment development flavor version code only as shown below.
DevelopmentVersion.properties
VERSION_MAJOR=1
VERSION_MINOR=0
VERSION_PATCH=0
VERSION_CODE=2
VERSION_BUILD=1
DevelopmentErrorVersion.properties
VERSION_MAJOR=1
VERSION_MINOR=0
VERSION_PATCH=0
VERSION_CODE=1
VERSION_BUILD=0
Important
As you can see DevelopmentVersion.properties
file contains DevelopmentErrorVersion.properties
previous incremental values, we are storing these values as backup if any error occurs during broken build. Later on we can revert these changes.
In case we encounter any error during incremental task or external errors we need to revert changes which are made in version properties files using revertVersionCodeForVariant
gradle task. It takes single command line parameter i.e. buildVariantType
Example
gradlew -PbuildVariantType=development revertVersionCodeForVariant
Above code snippet will revert Incremental changes made in development flavor version properties file
Fastlane provides huge collection of tools and scripts which we can use to automate our respective daily task.
How to setup Fastlane in Android Project visit fastlane docs
Generate Build for Development Variant and deploy build on crashlytics beta
fastlane devVariant
Generate Build for QA Variant and deploy build on crashlytics beta
fastlane qaVariant
Following are few Fastlane Actions and different techniques used to create Development Variant and Qa Variant lanes.
- Ensure Git Branch
- Ensure Git Status Clean
- Last Git Commit
- Git Commit
- Reset Git Repo
- Push To Git Remote
- Puts
- Is CI
- Gradle
- Crashlytics
You can define environment variables in a .env
or .env.default
file in the same directory as your Fastfile. Environment variables are loading using dotenv. Here's an example.
WORKSPACE=YourApp.xcworkspace
HOCKEYAPP_API_TOKEN=your-hockey-api-token
fastlane
also has a --env
option that allows loading of environment specific dotenv files. .env
and .env.default
will be loaded before environment specific dotenv files are loaded. The naming convention for environment specific dotenv files is .env.
fastlane <lane-name> --env development
Above code snippet will load .env
, .env.default
, and .env.development
Credentials should only be accessible on the machines that need access to them. Never commit sensitive information to a repository that is not needed by every development machine and server.
Personally, I prefer to commit the .env file with development-only settings. This makes it easy for other developers to get started on the project without compromising credentials for other environments. If you follow this advice, make sure that all the credentials for your development environment are different from your other deployments and that the development credentials do not have access to any confidential data.
Approach which we took in automating version type is inspired by Pivotal Tracker SCM Post-Commit Message Syntax we followed the same technique and introduced few keywords which are case sensitive and are listed below.
- Major
- Minor
- Patch
- Build
Example
[Patch] Fixed battery extensive usage.
Important
If multiple
Version Type
Tag are found in a commit we process only first successful matched tag and ignore rest of the them.
Example
[Major] [Build] Fixed battery extensive usage.[Patch]
As shown above we found multiple version type
tags in git commit, we will only extract [Major]
tag and processed the build with this, rest of the tag will be ignored.
When using git_commit
action to commit changes to remote repository in fastlane setup. If you are using webhooks to trigger build on a push this will cause an infinite loop of triggering builds.
We need to configure our CI to ignore build triggering which contains [ci-skip]
tag in commit message.
If you are using Gitlab you will need the GitLab Plugin. Inside the job you want to configure, go to Build Triggers > Build when a change is pushed to GitLab > Enable [ci-skip]
. When you include [ci-skip]
in your build this commit won't trigger the build in jenkins at all.
git_commit(path:"./CHANGELOG.md", message:"[ci-skip] Updated CHANGELOG for Build #{build_number}")
push_to_git_remote
- Support Multiple Crashlytics accounts
- Setup Travis-CI/Circle-CI/GitLab-CI
- Inject required credentials from CI environment variable
- Support Slack/EmailNotifications
- Fastlane - tool for iOS, Mac, and Android developers to automate tasks
- Gradle - Dependency Management
Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.
This project is licensed under the MIT License - see the LICENSE.md file for details
- A big thanks to Fastlane Team for its amazing tool.
- A big thanks to Kevin Long for its comprehensive article