Version automatique du projet Android de Git describe avec Android Studio / Gradle

j'ai cherché beaucoup, mais probablement en raison de la nouveauté D'Android Studio et Gradle, Je n'ai pas trouvé de description de la façon de faire cela. Je veux faire essentiellement exactement ce qui est décrit dans ce post , mais avec Android Studio, Gradle et Windows plutôt que Eclipse et Linux.

31
demandé sur Community 2013-06-14 01:19:13

9 réponses

une façon plus correcte et plus simple d'atteindre le résultat qui a gagné en traction récemment serait d'utiliser Grad git integration via Groovy jgit bindings . Comme il utilise JGit, il n'a même pas besoin de Git pour fonctionner.

voici un exemple de base montrant une solution similaire (mais avec quelques informations supplémentaires dans la chaîne gitVersionName):

buildscript {
  dependencies {
    classpath 'org.ajoberstar:grgit:1.4.+'
  }
}
ext {
  git = org.ajoberstar.grgit.Grgit.open()
  gitVersionCode = git.tag.list().size()
  gitVersionName = "${git.describe()}"
}
android {
  defaultConfig {
    versionCode gitVersionCode
    versionName gitVersionName
  }
}
[...]

comme vous pouvez le voir dans Grgit documentation de l'API le décrire le fonctionnement fournit des informations supplémentaires autres que les plus récentes de la balise accessible dans l'histoire:

trouver l'étiquette la plus récente qui est accessible depuis la tête. Si la balise pointe vers la propagation, seule la balise est affichée. Sinon, il suffixe le nom de la balise avec le nombre de commits supplémentaires sur le dessus de l'objet étiqueté et le nom abrégé de l'objet de la plus récente commit.

de toute façon, il ne dira pas si l'état est sale ou pas. Cette information peut être facilement ajouté à cette 1519200920" statut de l'opération, et en ajoutant une chaîne si elle n'est pas propre.

22
répondu Diego 2017-01-03 15:57:08

mettez ce qui suit dans votre construction.dossier gradle pour le projet. Il n'est pas nécessaire de modifier le manifeste directement: Google a fourni les crochets nécessaires dans leur configuration.

def getVersionCode = { ->
    try {
        def code = new ByteArrayOutputStream()
        exec {
            commandLine 'git', 'tag', '--list'
            standardOutput = code
        }
        return code.toString().split("\n").size()
    }
    catch (ignored) {
        return -1;
    }
}

def getVersionName = { ->
    try {
        def stdout = new ByteArrayOutputStream()
        exec {
            commandLine 'git', 'describe', '--tags', '--dirty'
            standardOutput = stdout
        }
        return stdout.toString().trim()
    }
    catch (ignored) {
        return null;
    }
}
android {
    defaultConfig {
        versionCode getVersionCode()
        versionName getVersionName()
    }
}

notez que si git n'est pas installé sur la machine, ou s'il y a une autre erreur pour obtenir le nom/code de la version, il sera par défaut à ce qui est dans votre manifeste android.

36
répondu moveaway00 2013-08-02 16:20:32

après avoir vu moveaway00's answer et Avinash's comment on that answer , j'ai fini par utiliser ceci:

apply plugin: 'android'

def getVersionCode = { ->
    try {
        def stdout = new ByteArrayOutputStream()
        exec {
            commandLine 'git', 'rev-list', '--first-parent', '--count', 'master'
            standardOutput = stdout
        }
        return Integer.parseInt(stdout.toString().trim())
    }
    catch (ignored) {
        return -1;
    }
}

def getVersionName = { ->
    try {
        def stdout = new ByteArrayOutputStream()
        exec {
            commandLine 'git', 'describe', '--tags', '--dirty'
            standardOutput = stdout
        }
        return stdout.toString().trim()
    }
    catch (ignored) {
        return null;
    }
}

android {
    defaultConfig {
        versionCode getVersionCode()
        versionName getVersionName()
    }
}

j'ai modifié le code de moveaway00 pour inclure aussi le commentaire D'Avinash R. le code de version est maintenant le nombre de commits depuis master , comme c'est ce que le code de version est supposé être.

notez que je n'ai pas besoin de spécifier le code de version et le nom de la version dans le manifeste, Gradle a pris soin d'elle.

26
répondu Léo Lam 2017-05-23 12:02:38

encore une autre voie:

https://github.com/gladed/gradle-android-git-version est un nouveau plugin gradle qui calcule automatiquement les noms de version et les codes de version pour android.

il traite un grand nombre de cas spéciaux qui ne sont pas possibles en utilisant la solution acceptée:

  • étiquettes de version pour plusieurs projets dans le même repo
  • codes de la version étendue comme 1002003 pour 1.2.3
  • gradle tâches pour faciliter l'extraction des informations de version pour l'IC outils
  • etc.

Avertissement: je l'ai écrit.

10
répondu gladed 2016-01-14 02:11:42

Voici une autre solution qui nécessite des instructions au lieu de fonctions pour accéder à la ligne de commande. Avertissement: *nix seule solution

def gitSha = 'git rev-parse --short HEAD'.execute([], project.rootDir).text.trim()

// Auto-incrementing commit count based on counting commits to master (Build #543)
def commitCount = Integer.parseInt('git rev-list master --count'.execute([], project.rootDir).text.trim())

// I want to use git tags as my version names (1.2.2)
def gitCurrentTag = 'git describe --tags --abbrev=0'.execute([], project.rootDir).text.trim()

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"

    defaultConfig {
        applicationId "com.some.app"
        minSdkVersion 16
        targetSdkVersion 22
        versionCode commitCount
        versionName gitCurrentTag

        buildConfigField "String", "GIT_SHA", "\"${gitSha}\""

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

    }
}
4
répondu jpotts18 2015-05-20 16:38:26

d'une Autre manière, en utilisant Android Studio (Gradle): Regardez ce billet de blog: http://blog.android-develop.com/2014/09/automatic-versioning-and-increment.html

, Voici la mise en œuvre du blog:

android {
defaultConfig {
...
    // Fetch the version according to git latest tag and "how far are we from last tag"
    def longVersionName = "git -C ${rootDir} describe --tags --long".execute().text.trim()
    def (fullVersionTag, versionBuild, gitSha) = longVersionName.tokenize('-')
    def(versionMajor, versionMinor, versionPatch) = fullVersionTag.tokenize('.')

    // Set the version name
    versionName "$versionMajor.$versionMinor.$versionPatch($versionBuild)"

    // Turn the version name into a version code
    versionCode versionMajor.toInteger() * 100000 +
            versionMinor.toInteger() * 10000 +
            versionPatch.toInteger() * 1000 +
            versionBuild.toInteger()

    // Friendly print the version output to the Gradle console
    printf("\n--------" + "VERSION DATA--------" + "\n" + "- CODE: " + versionCode + "\n" + 
           "- NAME: " + versionName + "\n----------------------------\n")
...
}

}

2
répondu Sean 2014-09-07 06:11:27

S'il peut être d'une aide quelconque, j'ai mis en place un exemple de script Gradle qui utilise les tags Git et git describe pour réaliser ceci. Voici le code (vous pouvez aussi le trouver ici ).

1) Créer D'abord un versioning.Grad fichier contenant:

import java.text.SimpleDateFormat

/**
 * This Gradle script relies on Git tags to generate versions for your Android app
 *
 * - The Android version NAME is specified in the tag name and it's 3 digits long (example of a valid tag name: "v1.23.45")
 *   If the tag name is not in a valid format, then the version name will be 0.0.0 and you should fix the tag.
 *
 * - The Android version CODE is calculated based on the version name (like this: (major * 1000000) + (minor * 10000) + (patch * 100))
 *
 * - The 4 digits version name is not "public" and the forth number represents the number of commits from the last tag (example: "1.23.45.178")
 *
 */

ext {

    getGitSha = {
        return 'git rev-parse --short HEAD'.execute().text.trim()
    }

    getBuildTime = {
        def df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'")
        df.setTimeZone(TimeZone.getTimeZone("UTC"))
        return df.format(new Date())
    }

    /**
     * Git describe returns the following: [GIT_TAG_NAME]-[BUILD_NUMBER]-[GIT_SHA]
     */
    getAndroidGitDescribe = {
        return "git -C ${rootDir} describe --tags --long".execute().text.trim()
    }

    /**
     * Returns the current Git branch name
     */
    getGitBranch = {
        return "git rev-parse --abbrev-ref HEAD".execute().text.trim()
    }

    /**
     * Returns the full version name in the format: MM.mm.pp.ccc
     *
     * The version name is retrieved from the tag name which must be in the format: vMM.mm.pp, example: "v1.23.45"
     */
    getFullVersionName = {
        def versionName = "0.0.0.0"
        def (tag, buildNumber, gitSha) = getAndroidGitDescribe().tokenize('-')
        if (tag && tag.startsWith("v")) {
            def version = tag.substring(1)
            if (version.tokenize('.').size() == 3) {
                versionName = version + '.' + buildNumber
            }
        }
        return versionName
    }

    /**
     * Returns the Android version name
     *
     * Format "X.Y.Z", without commit number
     */
    getAndroidVersionName = {
        def fullVersionName = getFullVersionName()
        return fullVersionName.substring(0, fullVersionName.lastIndexOf('.'))
    }

    /**
     * Returns the Android version code, deducted from the version name
     *
     * Integer value calculated from the version name
     */
    getAndroidVersionCode = {
        def (major, minor, patch) = getAndroidVersionName().tokenize('.')
        (major, minor, patch) = [major, minor, patch].collect{it.toInteger()}
        return (major * 1000000) + (minor * 10000) + (patch * 100)
    }

    /**
     * Return a pretty-printable string containing a summary of the version info
     */
    getVersionInfo = {
        return "\nVERSION INFO:\n\tFull version name: " + getFullVersionName() +
                "\n\tAndroid version name: " + getAndroidVersionName() +
                "\n\tAndroid version code: " + getAndroidVersionCode() +
                "\n\tAndroid Git branch: " + getGitBranch() +
                "\n\tAndroid Git describe: " + getAndroidGitDescribe() +
                "\n\tGit SHA: " + getGitSha() +
                "\n\tBuild Time: " + getBuildTime() + "\n"
    }

    // Print version info at build time
    println(getVersionInfo());
}

2) puis éditez votre app/build.Grad pour l'utiliser comme ceci:

import groovy.json.StringEscapeUtils;

apply plugin: 'com.android.application' // << Apply the plugin

android {

    configurations {
        // ...
    }

    compileSdkVersion 22
    buildToolsVersion "22.0.1"

    defaultConfig {

        minSdkVersion 17
        targetSdkVersion 22

        applicationId "app.example.com"

        versionCode getAndroidVersionCode() // << Use the plugin!
        versionName getAndroidVersionName() // << Use the plugin!

        // Build config constants
        buildConfigField "String", "GIT_SHA", "\"${getGitSha()}\""
        buildConfigField "String", "BUILD_TIME", "\"${getBuildTime()}\""
        buildConfigField "String", "FULL_VERSION_NAME", "\"${getVersionName()}\""
        buildConfigField "String", "VERSION_DESCRIPTION", "\"${StringEscapeUtils.escapeJava(getVersionInfo())}\""
    }

    signingConfigs {
        config {
            keyAlias 'MyKeyAlias'
            keyPassword 'MyKeyPassword'
            storeFile file('my_key_store.keystore')
            storePassword 'MyKeyStorePassword'
        }
    }

    buildTypes {

        debug {
            minifyEnabled false
            debuggable true
        }

        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.config
            debuggable false
        }

    }

    productFlavors {
       // ...
    }

    dependencies {
        // ...
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
}

/**
 * Save a build.info file
 */
task saveBuildInfo {
    def buildInfo = getVersionInfo()
    def assetsDir = android.sourceSets.main.assets.srcDirs.toArray()[0]
    assetsDir.mkdirs()
    def buildInfoFile = new File(assetsDir, 'build.info')
    buildInfoFile.write(buildInfo)
}

gradle.projectsEvaluated {
    assemble.dependsOn(saveBuildInfo)
}

la partie La plus importante est d'appliquer le plugin

apply plugin: 'com.android.application'

et ensuite l'utiliser pour le nom de la version android et le code

versionCode getAndroidVersionCode()
versionName getAndroidVersionName()
2
répondu Soloist 2015-11-30 20:53:31

basé sur réponse de Léo Lam et mon précédent explorations sur la même solution pour ant, j'ai conçu un purement multiplateformes solution en utilisant jgit:

(original source )

fichier: Git-version.Grad

buildscript {
    dependencies {
        //noinspection GradleDynamicVersion
        classpath "org.eclipse.jgit:org.eclipse.jgit:4.1.1.+"
    }
    repositories {
        jcenter()
    }
}
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.revwalk.RevWalk
import org.eclipse.jgit.storage.file.FileRepositoryBuilder

import static org.eclipse.jgit.lib.Constants.MASTER

def git = Git.wrap(new FileRepositoryBuilder()
        .readEnvironment()
        .findGitDir()
        .build())

ext.readVersionCode = {
    def repo = git.getRepository()
    def walk = new RevWalk(repo)
    walk.withCloseable {
        def head = walk.parseCommit(repo.getRef(MASTER).getObjectId())
        def count = 0
        while (head != null) {
            count++
            def parents = head.getParents()
            if (parents != null && parents.length > 0) {
                head = walk.parseCommit(parents[0])
            } else {
                head = null
            }
        }
        walk.dispose()
        println("using version name: $count")
        return count
    }
}

ext.readVersionName = {
    def tag = git.describe().setLong(false).call()
    def clean = git.status().call().isClean()
    def version = tag + (clean ? '' : '-dirty')
    println("using version code: $version")
    return version
}

l'usage sera:

apply from: 'git-version.gradle'

android {
  ...
  defaultConfig {
    ...
    versionCode readVersionCode()
    versionName readVersionName()
    ...
  }
  ...
}
1
répondu Avinash R 2017-05-23 12:10:06

définit la fonction simple dans le fichier gradle:

def getVersion(){
    def out = new ByteArrayOutputStream();
    exec {
        executable = 'git'
        args = ['describe', '--tags']
        standardOutput = out
    }
    return out.toString().replace('\n','')
}

Utiliser:

project.version = getVersion()
0
répondu S.D. 2018-09-17 08:32:22