android git gradle android-studio auto-versioning

Versión de Android del proyecto de git describe automáticamente con Android Studio/Gradle



android-studio auto-versioning (8)

Aquí hay otra solución que requiere declaraciones en lugar de funciones para acceder a la línea de comandos. Advertencia: * nix solo solución

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'' } } }

He buscado mucho, pero probablemente debido a la novedad de Android Studio y Gradle, no he encontrado ninguna descripción de cómo hacer esto. Quiero básicamente hacer exactamente lo que se describe en esta publicación , pero con Android Studio, Gradle y Windows en lugar de Eclipse y Linux.


Coloque lo siguiente en su archivo build.gradle para el proyecto. No es necesario modificar el manifiesto directamente: Google proporcionó los enganches necesarios en su configuración.

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() } }

Tenga en cuenta que si git no está instalado en la máquina, o hay algún otro error al obtener el nombre / código de la versión, de manera predeterminada aparecerá lo que está en su manifiesto de Android.


Después de ver la respuesta de moveaway00 y el comentario de Avinash R sobre esa respuesta , terminé usando esto:

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() } }

He editado el código de moveaway00 para incluir también el comentario de Avinash R: el código de la versión ahora es el número de confirmaciones desde el master , ya que se supone que es el código de la versión.

Tenga en cuenta que no necesité especificar el código de la versión y el nombre de la versión en el manifiesto, Gradle se encargó de ello.


En base a la respuesta de Léo Lam y mis explorations anteriores sobre la misma solución para hormiga, he ideado una solución puramente multiplataforma utilizando jgit:

( source original)

Archivo: git-version.gradle

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 }

El uso será:

apply from: ''git-version.gradle'' android { ... defaultConfig { ... versionCode readVersionCode() versionName readVersionName() ... } ... }


Si puede ser de alguna ayuda, he configurado un script de Gradle de ejemplo que usa etiquetas de Git y describe a Git para lograr esto. Aquí está el código (también puedes encontrarlo here ).

1) Primero crea un archivo versioning.gradle que contenga:

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) Luego edite su aplicación / build.gradle para usarla así:

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 parte más importante es aplicar el complemento

apply plugin: ''com.android.application''

Y luego usarlo para el nombre y código de la versión de Android

versionCode getAndroidVersionCode() versionName getAndroidVersionName()


Una manera más apropiada y delgada de lograr el resultado que ganó fuerza últimamente sería usar la integración de gradle git a través de enlaces Groovy JGit . Como usa JGit, ni siquiera requiere que git se instale para funcionar.

Aquí hay un ejemplo básico que muestra una solución similar (pero con algo de información adicional en 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 } } [...]

Como puede ver en la documentación de la API de Grgit, la operación de descripción proporciona información adicional distinta a la etiqueta más reciente accesible en la historia:

Encuentra la etiqueta más reciente que se puede alcanzar desde HEAD. Si la etiqueta apunta a la confirmación, solo se muestra la etiqueta. De lo contrario, incluye el nombre de la etiqueta con el número de confirmaciones adicionales en la parte superior del objeto etiquetado y el nombre abreviado del objeto de la confirmación más reciente.

De todos modos, no dirá si el estado está sucio o no. Esta información se puede agregar fácilmente al observar el estado de limpieza del repositorio y agregar una cadena si no está limpio.


Otra forma más:

https://github.com/gladed/gradle-android-git-version es un nuevo plugin de gradle que calcula los nombres de versiones compatibles con android y los códigos de versión de forma automática.

Maneja muchos casos especiales que no son posibles usando la solución aceptada:

  • etiquetas de versión para proyectos múltiples en el mismo repositorio
  • códigos de versión ampliada como 1002003 para 1.2.3
  • tareas de gradle para extraer fácilmente información de versión para herramientas de CI
  • etc.

Descargo de responsabilidad: lo escribí.


Otra forma, usando Android Studio (Gradle): Echa un vistazo a esta publicación en el blog: http://blog.android-develop.com/2014/09/automatic-versioning-and-increment.html

Aquí está la implementación del 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") ... }

}