25. 04. 2018
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'
}