Preferred way to build a release


(Sverre Moe) #1

What is the preferred way to build a release in gradle? For those using Gradle over Maven, what is the process you are using for building a release?

I have been using Maven for years now and have begun to appreciate the strength and simplicity of gradle build script. I have written a gradle build script that builds my project exactly the same as with maven. Though I am missing the release process.
With maven release plugin the release is a two step process.

mvn release:prepare
mvn release:perform

It creates the git tag and two git commits for the release:

063f3d36b [maven-release-plugin] prepare for next development iteration
92d35d70f (tag: v1.0.0) [maven-release-plugin] prepare release v1.0.0

There is an gradle release plugin.

https://github.com/researchgate/gradle-release

$ gradle release -Prelease.useAutomaticVersion=true -Prelease.releaseVersion=1.0.0 -Prelease.newVersion=1.1.0-SNAPSHOT

Also an gradle git plugin that seems to have similar release feautures
https://github.com/ajoberstar/gradle-git

$ release -Prelease.scope=major -Prelease.stage=final

From what I see there is either using one of these gradle plugins to perform the release build, or do it manually.
$ sed -i 's/1.0.0-SNAPSHOT/1.0.0/g' build.gradle
$ git add build.gradle
$ git commit -m "Gradle Release v1.0.0"
$ git push
$ gradle build
$ git tag -a v1.0.0 -m "Gradle Release Build v1.0.0"
$ git push --tags
$ sed -i 's/1.0.0/1.1.0-SNAPSHOT/g' build.gradle
$ git add build.gradle
$ git commit -m "Gradle Release next development"
$ git push

This is a lot of work to do when we need to build a release.

Or perhaps have version always at 1.0.0-SNAPSHOT and not commit changes for version. Just change the version and build and create git tag for the release build. However we need some way to keep track on the previous version to increment, perhaps on a git tag.

$ gradle build -Prelease=true -PreleaseVersion=1.0.0

in build.gradle

if (release) {
    version = releaseVersion
}

(Sverre Moe) #2

I have been looking into the build scripts for Gradle itself. Many interesting examples.

One file caught my eyes:

What kind of plugin creates this file?

There is also a version.txt, I wonder what the purpose of it is. The version mentioned there is the next-next release (twice over).

How does gradle use these to actually release? Tempted to borrow the versioning.gradle for my project.


(Vyacheslav Rusakov) #3

Hello,

I come from Maven too and miss release process very much. Eventually, I choose to use https://github.com/researchgate/gradle-release

For me it is complete equivalent to maven release process.
You keep project version in gradle.properties file (inside the project). E.g. version=1.0.1-SNAPSHOT.
When you need to perform release, just do ./gradlew release and it will ask you about releasing version (and update it) and then about new version (100% the same as maven).

Usually, the only customization you need to do is attaching custom tasks to release cycle. In my case (mostly OSS projects) it’s bintray upload: afterReleaseBuild.dependsOn = [bintrayUpload]

You can see complete project example here: https://github.com/xvik/dropwizard-guicey/blob/master/build.gradle#L121

Another moment I missed after maven was “maven install” for local snapshots deployment. To fulfill this need I wrote https://github.com/xvik/gradle-java-lib-plugin. It also configures required jars (src, javadoc) and adds maven xml and properties inside main jar (as maven did). You don’t need to use plugin if you don’t want to, everything is described here https://github.com/xvik/gradle-java-lib-plugin#boilerplate-plugin-removes so you can just re-use some parts of this configuration.


(Filip Jirsák) #4

Hello,
I think version should not be set in project file (pom.xml or build.gradle), because during development version is meaningless. So I set version on command line only for release task (gradlew release -Pversion=x.y.z). My release task checks if property version is set. My steps for building release are the opposite to yours. I tag version in Git, build server then grabs that tag and runs gradle task. Version property is set according to tag name. So only manual thing I have to do is to find right commit and tag it by version number. The rest is done by build server automatically.


(Joffrey BION) #5

Hi Filip, if you tag the version yourself before the CI runs, then it means you create the tag before building, so you may end up tagging a commit that doesn’t CI-build (even if it does build locally). Have you ever had any problems like this?

Also, some projects do need the version at runtime, so you need it during development when you test this kind of feature. How do you deal with these?


(Filip Jirsák) #6

Hi Joffrey, I tag the commit after it was successfully built by CI, or after it was manually tested. So technically it is new build, but the only change should be version number. If I wanto to, I can tag one commit with different versions - for example first time I tag it version-1.0.0-RC3 and after all manual tests are successfully done I tag the same commit as final version-1.0.0.
In case I tag some version and CI fails on that tag (because of some bug leading into unreproducible build), I remove the version tag from repository and I tag fixed commit with the same version number (but it should be rare occurrence).

I use fixed string, for example “devel”, during development. This is what I have in one of my Gradle tasks:

file("$buildDir/web/static/version.txt").text = (project.version == 'unspecified' ? 'devel' : project.version)

If it is needed there can be commit number or timestamp in version number during development. I don’t use “production” version number scheme for development, because I think these development version numbers are fabricated - often version 1.2.5-SNAPSHOT became 1.3.0 and so on. I think Maven’s “-SNAPSHOT” is design mistake :slight_smile:


(Joffrey BION) #7

I agree with you in this respect, I never quite understood how people could know in advance what the next version would be when releasing a given version.
In my projects, I currently don’t even try to change anything and just leave the latest version I released in the build.gradle, but this feels wrong and I’m trying to find a clean solution to this.

The fixed string idea is a good idea, and maybe we simply don’t need more than that.
However, I was thinking about using a convention that’s the opposite of maven: rather than guessing the next version and expressing somehow that it’s not ready (“snapshot”), we could keep the latest released version, but with a marker saying that we added stuff to it since the release.
For example, after releasing “1.2.0”, we set the version to something like “1.2.0-NEXT”, or “1.2.0-NEXT.1234”, 1234 being some CI build number.


(Filip Jirsák) #8

Probably you can use gradle-git-version plugin. It assembles version number from last released version (from git tag name), git commit ID and „dirty“ suffix if needed. But I don’t know if this plugin can be used with current Gradle.