Gradle equivalent of maven-versions-plugin - maven

This is my build.gradle:
group 'whatever'
version '1.0.0-SNAPSHOT'
...
dependencies {
compile 'whatever:2.2.1-SNAPSHOT'
}
I want to automate releasing process, which includes the need to set both versions to particular values, e.g. 1.1.0 or 2.2.0 using command line only. Any kind of autoincrement is not an option.
With Maven, I'd do this using maven-versions-plugin:
mvn versions:set -DnewVersion=${WHATEVER_NEW_VERSION}
How can I do the same with Gradle? I only found this unanswered question. There must be some simple way to do that?

I ended up extracting version numbers to gradle.properties and updating them as part of the automated build script using sed:
sed -i -e \"/someVersionNumber=/ s/=.*/=${SOME_NEW_VERSION_NUMBER}/\" gradle.properties
It's what I want. Although for me, coming from the Maven background, this doesn't seem natural. I may research another alternative later.

Though not related to publishing, one way to pass command-line properties is as follows:
gradle -PWHATEVER_NEW_VERSION=2.0.0
Consider the following build.gradle snippet:
def newVersion = project."WHATEVER_NEW_VERSION"
println newVersion
See ~/utils/gradle/version.gradle in this project for another approach. It uses separate environment variables for major, minor, and incremental versions and then builds the string automatically. Because it resides in the gradle directory, it can simply be imported into build.gradle, which hides some boilerplate.

I successfully used Axion Release Plugin a couple of times and was very satisfied. Functionality-wise it comes the closest to what Maven's

Related

Maven overwrite version tag

In my project's POM file, there are some tags
<groupId>foo.bar</groupId>
<artifactId>foobar</artifactId>
<version>X</version>
<description>foo bar foo bar</description>
specified. I'm doing some builds using Jenkins and I want to overwrite that X value. How can I do that?
As an example, I'm more familiar with MSBuild and there I can do something like
msbuild.exe project.sln ...some options... /p:AssemblyVersion=X
Is that AssemblyVersion that I'm talking about. Is this possible with maven?
Besides that, is this even a good practice? At the moment, I have version 1.0-SNAPSHOT. Should I manually change that value? How to perform a release?
To update version in pom files automatically from Jenkins, use -DnewVersion argument along with mvn command.
Example:
mvn versions:set -DnewVersion=someversion
During buildtime, if you'd like to update the buildnumber as your artifact version, then you can just pass that environment variable like -DnewVersion=${BUILD_NUMBER}.
Edit 1:
Credits to this SO thread updating-version-numbers-of-modules-in-a-multi-module-maven-project. It has a clear explanation.

Make maven output show progressed sub-modules only

I am working with an automatic build script in maven 3.x. The parent project contains of more than 60 modules. The compilation is done in a shell script simplified this way:
for each module:
cd module
mvn clean install > compile.$module.log
echo "Compiled $module"
I like to see a list of compiled modules in order to see the progress or the build. I like to have a big maven command and avoid the manual for loop. I hope to speed up the build this way, since splitting the parent project into more independent modules is not a short time option, yet.
The --quiet flag might be enough already. Alternatively a user defined logging implementation would be fine as well, as described in the manual (https://maven.apache.org/maven-logging.html)
The questions are:
What is the prefered way to modify maven log output?
Does anyone already know a ready-to-use plugin for my purpose?
Thanks

Appyling Gradle signing plugin, without requiring a GPG keyring

I am following the instructions at http://central.sonatype.org/pages/gradle.html to use Gradle to upload artifacts to the Maven Central Repository. The instructions work. Examples appear at https://github.com/plume-lib/options/blob/master/build.gradle and https://github.com/plume-lib/bcel-util/blob/master/build.gradle .
My problem is that it results in a buildfile that other developers cannot use.
The Gradle signing plugin (https://docs.gradle.org/current/userguide/signing_plugin.html) requires a gradle.properties file with signing.keyId, signing.password, and signing.secretKeyRingFile, where the latter points to a valid GPG keyring. The plugin terminates the build with an error if the file doesn't exist or is not valid.
But signing is only needed when uploading artifacts to Maven Central.
I want any user to be able to run the gradle buildfile (except for actually uploading to Maven Central), even if they do not have a GPG keyring.
How can I achieve this?
Here are some things I have tried:
Split the gradle file into parts. (This is what is shown in the linked examples.) This requires two changes.
Change the main buildfile into a build script. (It can still be invoked from the command line). One gross thing about this is that only a gradle buildfile can contain a plugins { ... } block, and referring to a plugin outside the plugins { ... } block is verbose and ugly, as at the bottom of (say) https://plugins.gradle.org/plugin/com.github.sherter.google-java-format or
Create another buildfile, used only for signing, that uses apply from: to include the main one.
Question: Is there a way to do this without the ugly buildscript block?
Commit a dummy keyring to the repository, refer to it in the local gradle.properties, and the user's ~/gradle.properties can override it for any user who wants to upload to Maven Central. A problem is that using a local pathname yields a gradle warning.
Question: Is there a way to do this without a gradle warning?
Use conditional signing (https://docs.gradle.org/current/userguide/signing_plugin.html). In my experiments, this does not help. Even on a gradle execution where the artifacts are not signed, the signing plugin still requires the GPG keyring to exist.
Question: Can conditional signing be used to avoid the need for a GPG keyring?
Question: Is there a better way to achieve my goals than the above possibilities?
The documentation has a section on "Conditional Signing" which is exactly what you need here.
And you can even make that condition check that the required properties are indeed available to the build.

Getting unique version numbers with Jenkins and Maven

I'm working on a multi module maven project with Jenkins. I have a Build-Job which I want to package my project with a unique version number and deploy it to Nexus.
The version number should be - where the "maven-version" is the version maintained in the root POM and "build-number" is Jenkins' job build number. For example: 1.2.3-1234
I'm using the maven-versions-plugin to set the desired version number but I have the problem that I want to have the first part of the version (1.2.3) maintained in the POM. So I need a way to extrakt the version from the POM into a Jenkins environment variable.
Until yet I found no direct way of doing this. My solution is to use a groovy script which pares the POM and writes the version number into a temporary property file. After that I use the EnvInject plugin to create the environment varaible for later reinjecting as version number for the "mvn versions:set" command.
My groovy script:
import jenkins.util.*;
def project = new XmlSlurper().parse(new File("pom.xml"))
def version = project.version.toString();
def mainversion = version.substring(0, version.indexOf("-SNAPSHOT"));
println "Version: $mainversion";
def versionFile = new File("v.properties");
versionFile << "VERSION=$mainversion";
This indirection through the property file is very ugly and error prone. Is there any way to directly create an environment variable within the groovy script? It is possible using a system groovy script but these kind of scripts are always executed on the master. So my job will not be runable on slaves which doesn't work for me because I do not execute builds on the master.
Welcome to another version of the Jenkins Chain upstream-downstream variable problem. I assume you are probably trying to do some sort of continuous integration pipeline.
At my company, we solved this one of two ways:
Option 1: Brute force by doing a sed search and replace as a execute shell in the beginning:
#sed -i '0,/<version>.*<\/version>/s/<version>.*<\/version>/<version>'${SVN_REVISION}'<\/version>/g' pom.xml;
#sed -i '0,/<name>.*<\/name>/s/<name>.*<\/name>/<name>'"${JOB_NAME}"'<\/name>/g' pom.xml;
#find . -name pom.xml | xargs sed -i 's/${build.number}/'${SVN_REVISION}'/g';
Option 2: Use Artifactory instead of Nexus and pay for Artifactory Pro. The Build/Release Management functions of the Artifactory jenkins plugin have saved us hours and hours of this kind of grief.

how to prevent gradle from downloading dependencies

We would like to have a script that does "svn update" and if the depedency.gradle file is in that list of updates, we would like to run a task that ONLY updates dependencies so the developers machine is up to date. What would that task be? I don't see it when running "gradle tasks". Looking for an updatejars or something.
When we build our project, we don't want it to check for jar updates at all!!!! most because that only needs to be done in 2 situations which are #1 above and when someone is updating the dependency.gradle file themselves. For the second thing, they can just run "gradle updatejars" once I know the answer to question #1 that is.
Any ideas? I am just getting into gradle and we really want to keep a consistent environment where when we run our update script, it gets the source code AND the jars in one atomic sweep and we are no longer bothered by checking the repositories every build.
It would be nice to know how to do it by changing the build.gradle file if possible. If not, is there a command line option? (The build.gradle obviously would give me a command line option which is why I prefer that method as I could say compile does not depend on downloading jars).
Regarding the second question. As far as I understand, Gradle will not attempt to do remote lookups or try to download the jar if it is already in the local cache. This should be true for jars declared with a static version, e.g. testCompile 'junit:junit:4.10'.
If you have dynamic versions, e.g. 1.+ or 1.0-SNAPSHOT, etc. then Gradle has to do a check every now and then. You can fine tune the cache expiry for such dependencies.
To make sure Gradle does not do remote lookups you can also use --offline option. See this doc for details.
With regard to svn update, you have at least 3 options:
Try to use an SvnKit plugin for Gradle
Use the ant svn task (here's how to do svn checkout)
Run external command from Gradle. Use the ExecPlugin or just implement it yourself using Groovy API.
Looks like the 1st question I can do with the answer in this post
how to tell gradle to download all the source jars
so I can just gradle eclipse and it will download new jars and update my classpath...nice.

Resources