Managing your project version with gradle plugins

In a previous post we saw that we could dynamically construct our version based on the state of our repository.

However if we do not want to go through the hassle of creating such a function ourselves, we could always use one of the many versioning gradle plugins available.

A simple search on the gradle plugins portal will yield several pages of plugins for us to choose from.

I first tried the nebula-release-plugin. The changes to my build.gradle were quite simple: remove my custom calculate function (and its use under allprojects) and simply appy the plugin:

plugins {
   id 'nebula.nebula-release' version '4.0.1'
}

This will give you versioning out of the box depending on your branch, and on several commandline parameters.

The plugin is quite configurable. However it includes steps to push to remote repositories that you might not want to enforce, and it’s not straightforward to remove such steps.

Intrigued, I tried gradle-git, since the nebula plugin is based on it. However it suffers from the same problem as the nebula plugin, it asks for credentials for fetching and pushing to the git repository (I do not necessarily want the plugin to do the pushing for me).

The nebula plugin had some provisions to at least ignore git checks via an undocumented property: release.disableGitChecks, but then it will not tag the commit either (not too problematic).

In the end I went back to the nebula-release-plugin, but configuring ssh keys to avoid annoying credentials propmting. I like that it integrates with normal gradle-java tasks, so I can still run gradlew build and I will get a development version automatically:

ME@MYPC MINGW64 /d/DatosXP/fuentes/pruebas-de-stash-y-jira (develop)
$ ./gradlew build
-------------------------------------------------
Inferred project: javagittest, version: 1.8.0-dev.13+2401da1
Prueba de git y java - version: 1.8.0-dev.13+2401da1
-------------------------------------------------
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:jar
:assemble
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build

BUILD SUCCESSFUL

Total time: 7.554 secs

If I want to tag a new release I will use one of the tasks provided by the plugin (mind your branches):

ME@MYPC MINGW64 /d/DatosXP/fuentes/pruebas-de-stash-y-jira (release/1.8.x)
$ ./gradlew candidate
-------------------------------------------------
Inferred project: javagittest, version: 1.8.0-rc.1
Prueba de git y java - version: 1.8.0-rc.1
-------------------------------------------------
:releaseCheck
:candidate
:prepare
:compileJava UP-TO-DATE
[...]
:check UP-TO-DATE
:build
:release
Tagging repository as v1.8.0-rc.1
Pushing changes in [refs/heads/release/1.8.x, v1.8.0-rc.1] to origin

BUILD SUCCESSFUL

Total time: 9.989 secs

This will push the new tag to our origin remote, so we need to be careful with it.

When we are happy with the final version (for example after merging into master) we can make the final release, which will be also tagged and pushed:

ME@MYPC MINGW64 /d/DatosXP/fuentes/pruebas-de-stash-y-jira (master)
$ ./gradlew final
-------------------------------------------------
Inferred project: javagittest, version: 1.8.0
Prueba de git y java - version: 1.8.0
-------------------------------------------------
:releaseCheck
:final
:prepare
:compileJava UP-TO-DATE
[...]
:check UP-TO-DATE
:build
:release
Tagging repository as v1.8.0
Pushing changes in [refs/heads/master, v1.8.0] to origin

BUILD SUCCESSFUL

Total time: 9.685 secs

If we want to re-build this version (at a CI server for example) we can use the property -Prelease.useLastTag=true in the gradlew command.

Other useful properties are -Prelease.scope=major or -Prelease.scope=patch if we want the version bump to increase the major or the patch part of the version instead of the default (minor).

[2016/06/01 Update]

These past days I’ve been struggling a little bit trying to use the nebula-release plugin but it really bothers me that the plugin pushes things for me.

Yesterday I found another very promising plugin, greatly configurable, which doesn’t force the push on me: enter axion-release-plugin

After a few hours testing and reading the docs I have come up with my initial configuration which does all I wanted:

  • autoincrementing version
  • adding -SNAPSHOT automatically for not-tagged-commits
  • versioning scheme configurable per branch
  • support for major.minor.patch-rcX
  • access to the version without need for tagging

In case you are curious, my initial config looks like this:

scmVersion {
    tag {
        prefix = ''
    }

    // Incrementing policy
    versionIncrementer 'incrementMinor'  //default
    branchVersionIncrementer = [
       'master': 'incrementPrerelease',
       'release/.*': 'incrementPrerelease',
       'hotfix/.*': 'incrementPrerelease'
    ]

    // Decorators
    versionCreator 'simple'
    branchVersionCreator = [
       'feature/.*': 'versionWithBranch'
    ]

    localOnly = true  //no pushing to remote
}

And I can access the version without building like this:

ME@MYPC MINGW64 /d/DatosXP/fuentes/pruebas-de-stash-y-jira (feature/switch_to_gradle)
$ ./gradlew currentVersion
:currentVersion

Project version: 1.1.0-feature-switch_to_gradle-SNAPSHOT

BUILD SUCCESSFUL

Total time: 8.643 secs

Be sure to visit axion’s page as it has outstanding documentation.

This plugin fits like a glove!

Leave a comment