11.6.2015

Last Updated on

Nebaví tě ručně zvyšovat verzi aplikace při každém vydání nové verze? V tomto článku si ukážeme jak nastavit verzi pomocí GIT tagu. Dává to perfektní smysl, každou verzi si totiž stejně chceme otagovat, tak proč rovnou nevyužít tag i pro definování verze.

Otagování verze v GITu

Napřed si definujme standardizované jméno tagu, které budeme dále používat:

{stage}/{x}.{y}.{z}

kde {stage} je něco jako alpha, beta, release a {x}, {y}, {z} čísla major, minor a build verze. Vytvořme si testovací GIT tag zavoláním:

git tag release/0.2.1 -a

Poslední commit jsme si tím otagovali jako release s verzí 0.2.1, pokud si chcete přečíst jaký tag jste to vytvořili, zavolejme:

git describe --match 'release/*' --long

Máme vyřešený GIT, pojďme na Gradle!

Přečtení verze v Gradle

Pomocí příkazové příkazové řádky si přečteme poslední tag vytvořený pro konkrétní build variantu, jak bylo zmíněno výše. Výsledkem je jednoduchá funkce pro čtení a parsování verze z GIT tagu:

def getVersionTag = { variant ->
     def stdout
    try {
        stdout = new ByteArrayOutputStream()
        exec {
             commandLine "git", "describe", "--match", "${variant}/*", "--long"
             standardOutput = stdout
        }
        def longTag = stdout.toString().trim()

        return longTag.substring(longTag.indexOf('/') + 1, longTag.indexOf('-'))
     } catch (exception) {
        return "0.0.1";
     }
}

Na výstupu z této metody bude pro náš testovací tag „0.2.1“, tedy verze bez build variant prefixu. Tím máme v podstatě hotový version name, ještě potřebujeme version code:

def getVersionCode = { tag ->
    def parts = tag.tokenize('.')
    if(parts.size() != 3 || parts[1].length() > 2 || parts[2].length() > 2) {
        throw new RuntimeException("Invalid version tag \"${tag}\", format \"x.y.z\" expected.")
    }
    if(parts[1].length() == 1) {
        parts[1] = "0" + parts[1]
    }
    if(parts[2].length() == 1) {
        parts[2] = "0" + parts[2]
    }
    return Integer.parseInt(parts[0] + parts[1] + parts[2])
}

def getVersionName = { tag ->
    return tag
}

Použití verze z GITu ve všech build variantách

Nakonec aplikujeme version name a code na všechny build varianty. Následující kus scriptu, přidaný na konec android sekce, nám to zařídí:

android {
     applicationVariants.all { variant ->
        def versionTag = getVersionTag(variant.buildType.name)
        def myVersionCode = getVersionCode(versionTag)
        def myVersionName = getVersionName(versionTag)

        println variant.name + "[" + myVersionCode + ", " + myVersionName + "]"

        variant.mergedFlavor.versionName = myVersionName;
        variant.mergedFlavor.versionCode = myVersionCode;
    }
}

Celý build.gradle script

Máme hotovo, takto nějak může vypadat kompletní Gradle script:

apply plugin: 'com.android.application'

def getVersionTag = { variant ->
    def stdout
    try {
        stdout = new ByteArrayOutputStream()
        exec {
            commandLine "git", "describe", "--match", "${variant}/*", "--long"
            standardOutput = stdout
        }
        def longTag = stdout.toString().trim()

        return longTag.substring(longTag.indexOf('/') + 1, longTag.indexOf('-'))
    } catch (exception) {
        return "0.0.1";
    }
}

def getVersionCode = { tag ->
    def parts = tag.tokenize('.')
    if(parts.size() != 3 || parts[1].length() > 2 || parts[2].length() > 2) {
        throw new RuntimeException("Invalid version tag \"${tag}\", format \"x.y.z\" expected.")
    }
    if(parts[1].length() == 1) {
        parts[1] = "0" + parts[1]
    }
    if(parts[2].length() == 1) {
        parts[2] = "0" + parts[2]
    }
    return Integer.parseInt(parts[0] + parts[1] + parts[2])
}

def getVersionName = { tag ->
    return tag
}

android {

    compileSdkVersion 22
    buildToolsVersion "22.0.1"

    defaultConfig {
        applicationId "net.skoumal.gittagversion"
        minSdkVersion 14
        targetSdkVersion 22
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

     applicationVariants.all { variant ->
         def versionTag = getVersionTag(variant.buildType.name)
         def myVersionCode = getVersionCode(versionTag)
         def myVersionName = getVersionName(versionTag)

         println variant.name + "[" + myVersionCode + ", " + myVersionName + "]"

         variant.mergedFlavor.versionName = myVersionName;
         variant.mergedFlavor.versionCode = myVersionCode;
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.1.1'
}
Vladislav Skoumal
SKOUMAL CEO