Gradle script to autoversion and include the commit hash in Android

AndroidGitAndroid StudioGradleVersioning

Android Problem Overview


I need to write a gradle script to auto version my application on every commit. I need to also include the commit hash as a reference in the application for testers.

I am confused how auto versioning usually work. Can someone explain the autoversioning process?

Android Solutions


Solution 1 - Android

I encountered a similar problem, but did not want to modify the versionName to include the git hash. We wanted to keep that as something like 1.2.2, but still have the possibility of displaying the git hash in the UI.

I modified the code from the other answer here to use the buildConfigField task to generate a BuildConfig.GitHash value that can be referenced in the Java code.

Add this above the android section of your module's build.gradle file:

def getGitHash = { ->
    def stdout = new ByteArrayOutputStream()
    exec {
        commandLine 'git', 'rev-parse', '--short', 'HEAD'
        standardOutput = stdout
    }
    return stdout.toString().trim()
}

Then add the following line to the defaultConfig section of the android section of the build.gradle, i.e. below versionName:

buildConfigField "String", "GitHash", "\"${getGitHash()}\""

This generates the following line in the auto-generated BuildConfig.java file:

// Fields from default config.
public static final String GitHash = "e61af97";

Now you can get the git hash in your Java code with BuildConfig.GitHash.

Solution 2 - Android

One ideal solution could be grabbing the version from the git status of the project. This way the versioning does not rely on you remembering to increase a variable, or change any text in the gradle or config files. Another advantage is the traceability of the version name and code to one specific code status.

You can find one descriptive example in http://ryanharter.com/blog/2013/07/30/automatic-versioning-with-git-and-gradle/

The idea is getting the git info with the getVersionName function, and use that function in the gradle script:

/*
 * Gets the version name from the latest Git tag
 */
def getVersionName = { ->
    def stdout = new ByteArrayOutputStream()
    exec {
        commandLine 'git', 'describe', '--tags'
        standardOutput = stdout
    }
    return stdout.toString().trim()
}

kts:

val gitDescribe: String by lazy {
    val stdout = ByteArrayOutputStream()
    rootProject.exec {
        commandLine("git", "describe", "--tags")
        standardOutput = stdout
    }
    stdout.toString().trim()
    /* 'g' doesn't belong to the commit id and stands for 'git'
       v0.1.9-1-g3a259e0 -> v0.1.9-1-3a259e0
       if you like this to be removed then */
    //.replace("-g", "-") 
}

Of course, you need to have command line git available (as the command git describe --tags will be executed to generate the information).

Another approach (based also in getting the version info from git) could be externalizing that logic to a gradle plugin - such as:

The one to use will depend on which kind of versioning policy you want to apply.

Solution 3 - Android

add following code to your build.gradle

def gitCommitHash = 'git rev-parse --verify --short HEAD'.execute().text.trim()
defaultConfig{
    ... otherConfigs
    buildConfigField("String", "GIT_HASH", "\"${gitCommitHash}\"")
}

now you can get git hash by BuildConfig.GIT_HASH

have fun

Solution 4 - Android

I created a Gradle plugin to do this for you. The project and full instructions are at https://github.com/lessthanoptimal/gversion-plugin

To use it add the following to your build.gradle file

plugins {
  id "com.peterabeles.gversion" version "1.2.4"
}
 
gversion {
  srcDir = "src/main/java/"
  classPackage = "com.your.package"
  className = "MyVersion"                   // optional. If not specified GVersion is used
  dateFormat   = "yyyy-MM-dd'T'HH:mm:ss'Z'" // optional. This is the default
  timeZone     = "UTC"                      // optional. UTC is default
}

Now you just need to run the gradle task 'createVersionFile' to create the file. You might want to consider adding the following line to your gradle project project.compileJava.dependsOn(createVersionFile) This will cause it to generate the file every time Gradle builds the project. See the website above for Android instructions.

Here's what the file looks like

/**
 * Automatically generated file containing build version information.
 */
public class MyVersion {
	public static final String MAVEN_GROUP = "com.your";
	public static final String MAVEN_NAME = "project_name";
	public static final String VERSION = "1.0-SNAPSHOT";
	public static final int GIT_REVISION = 56;
	public static final String GIT_SHA = "a0e41dd1a068d184009227083fa6ae276ef1846a";
	public static final String BUILD_DATE = "2018-04-11T12:19:03Z";
	public static final long BUILD_UNIX_TIME = 1523449143116L;
}

You might also want to add the version file to your .gitignore since it is autogenerated and you don't want it in git.

Solution 5 - Android

Also worth looking at grgit - Groovy/Gradle Git, which can help simplify extraction of information, including Git commit-hashes, in a Gradle script.

Solution 6 - Android

This is a solution for Kotlin DSL (build.gradle.kts) derived from Charlie Lee's answer:

task<Exec>("MyTask") {
    doLast {
        commandLine("git")
            .args("rev-parse", "--verify", "--short", "HEAD")
            .workingDir(rootProject.projectDir)
    }
}

Another approach using the Java standard ProcessBuilder API:

tasks.create("MyTask") {
    val command = "git rev-parse --verify --short HEAD"
    doLast {
        val process = ProcessBuilder()
            .command(command.split(" "))
            .directory(rootProject.projectDir)
            .redirectOutput(Redirect.INHERIT)
            .redirectError(Redirect.INHERIT)
            .start()
        process.waitFor(60, TimeUnit.SECONDS)
        val result = process.inputStream.bufferedReader().readText()
        println(result)
    }
}

For more information see:

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionShatazoneView Question on Stackoverflow
Solution 1 - AndroidPaulView Answer on Stackoverflow
Solution 2 - AndroidAdrián Moreno PeñaView Answer on Stackoverflow
Solution 3 - AndroidCharlie LeeView Answer on Stackoverflow
Solution 4 - AndroidlessthanoptimalView Answer on Stackoverflow
Solution 5 - AndroidjavabrettView Answer on Stackoverflow
Solution 6 - AndroidMahozadView Answer on Stackoverflow