Getting Project Version from Maven POM in Jenkins

MavenJenkins

Maven Problem Overview


Is there any way a Jenkins build can be aware of the Maven version number of a project after processing the POM?

I've got some projects where versioning is controlled by Maven, and in a post-build job we'd like to create a Debian package and call some shell scripts. What I need is for the version number that Maven used to be available as a Jenkins environment variable so I can pass it to post-build actions.

To be clear, I'm not needing to know how to get Jenkins to pass a version number to Maven; instead I want Maven to pass a version number to Jenkins!

Maven Solutions


Solution 1 - Maven

You can use the ${POM_VERSION} variable, which was introduced with https://issues.jenkins-ci.org/browse/JENKINS-18272

Solution 2 - Maven

After a lot of digging around (I never realised how poorly-documented Jenkins is!) I found a quite trivial solution.

  1. Install the Groovy plugin
  2. Add a Post Step to your Maven build of type Execute **system** Groovy script
  3. Paste in the following snippet of Groovy:

Script:

import hudson.model.*;
import hudson.util.*;

def thr = Thread.currentThread();
def currentBuild = thr?.executable;
def mavenVer = currentBuild.getParent().getModules().toArray()[0].getVersion();
def newParamAction = new hudson.model.ParametersAction(new hudson.model.StringParameterValue("MAVEN_VERSION", mavenVer));
currentBuild.addAction(newParamAction);

The build environment variable called MAVEN_VERSION will now be available for substitution into other post-build steps in the usual manner (${MAVEN_VERSION}). I'm using it for Git tagging amongst other things.

Solution 3 - Maven

As other answers already pointed out, if you are using the Maven project type, you have access to the $POM_VERSION variable. But if you are not, you can use this sequence of steps (ugly but reliable). Doing it this way relies on the same version of maven to determine the pom version (while handling complex parent/child pom inheritance where <version> may not even be present for the child).

  1. Maven step with this goal:

    org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version -l version.log

  2. Shell step: (You may need to adjust the path to version.log depending on your hierarchy)

    echo "POM_VERSION=$(grep -v '\[' version.log)" > props.properties

  3. Inject Environment Variables step (Environment Injector Plugin):

    Properties File Path: props.properties

Now you can use $POM_VERSION as if this were a Maven project.

What this does: Uses maven to print out the version together with a mess of output, then greps out the mess of output leaving just the version, writes it to a file using properties file format and then injects it into the build environment. The reason this is better than a one-liner like mvn ..... | grep -v '\[' is that using a Maven step does not make assumptions about the installed maven versions and will be handled by the same auto-installation as any other maven steps.

Solution 4 - Maven

I used [Pipeline Utility Steps][1] plugin in a declarative pipeline job to get Maven version. In the example below I use script variable instead of environment variable, because that can be modified and passed between stages.

def TAG_SELECTOR = "UNINTIALIZED"
pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                sh "mvn --batch-mode -U deploy"
                script {
                    TAG_SELECTOR = readMavenPom().getVersion()
                }
                echo("TAG_SELECTOR=${TAG_SELECTOR}")
            }
        }
    }
}

Note: You must approve the getVersion() method after creating the job in Manage jenkins > In-process Script Approval.

See also:

Solution 5 - Maven

We used the Groovy Postbuild Plugin.

	String regex = '.*\\[INFO\\] Building .+ (.+)';
	def matcher = manager.getLogMatcher(regex);
	if (matcher == null) {
		version = null;
	} else {
		version =  matcher.group(1);
	}

Adding this to Jenkins for use later is a bit tricky. Give this a shot, although I remember this causing us some headaches. (Sorry, we did this a long time ago)

def addBuildParameter(String key, String value) {
    manager.build.addAction(new hudson.model.ParametersAction(new hudson.model.StringParameterValue(key,value))); 
}

Solution 6 - Maven

Had the same need and solved as suggested with Groovy parsing the pom.

import jenkins.util.*;
import jenkins.model.*;

def thr = Thread.currentThread();
def currentBuild = thr?.executable;
def workspace = currentBuild.getModuleRoot().absolutize().toString();

def project = new XmlSlurper().parse(new File("$workspace/pom.xml"))

def param = new hudson.model.StringParameterValue("project.version", project.version.toString())
currentBuild.addAction(new hudson.model.ParametersAction(param));

Add this script as a post step of type "Execute system Groovy script" (so it's not needed to install Groovy) and paste the code in the "Groovy command".

Solution 7 - Maven

Execute the Maven Plugin "exec-maven-plugin" in "Execute Shell" as a "Conditional step" worked for me:

mvn -q -Dexec.executable="echo" -Dexec.args='${projects.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.3.1:exec

Integrate in Jenkins:

-> "Add post-build step"
	-> "Conditional steps (single or multiple)"
		-> "Execute Shell:"

> export MY_POM_VERSION=`mvn -q -Dexec.executable="echo" > -Dexec.args='${projects.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.3.1:exec` && [[ > "${MY_POM_VERSION}" == "THE_VERSION_TO_BE_MATCHED" ]] && echo > "CONDITION_IS_MET"

	-> "Steps to run if condition is met"
		-> Add any build step you need

Notes:

  • THE_VERSION_TO_BE_MATCHED has to exchanged with your version
  • '&& echo "CONDITION_IS_MET"' is only for debugging purposes. For the same purpose you can add a '&& echo "MY_POM_VERSION=${MY_POM_VERSION}"' after the mvn command in order to understand what's going on.

This approach is more reliable than a "grep" and it could be an alternative if the Jenkins Ruby Plugin is not installed.

Solution 8 - Maven

You could also do :

MAVEN_VERSION=`grep A -2 -B 2 "<your_project_name>" pom.xml | grep version | cut -d\> -f 2 | cut -d\< -f 1`-commit-"`echo $GIT_COMMIT`"

Explanation: assuming that you have your project name within a line or two above/below version like a normal pom:

<groupId>org.apache.bigtop</groupId>
<artifactId>bigpetstore</artifactId>
<version>1.0-SNAPSHOT</version>

Then you can easily grep for the artifactId, use the "before/after" grep actions to suck in the version with it, and then grep the version out and use the simple unix "cut" command to splice out the content between "version" tags.

I like the Jenkins-groovy integration, but this is alot easier and will work even on a build server which you dont have control over (i.e. because bash is universal).

Solution 9 - Maven

Solution:

POM_VERSION=$( \
    xmlstarlet sel \
    -N x='http://maven.apache.org/POM/4.0.0' \
    -t \
    -v '//x:project/x:version/text()' \
    pom.xml \
)

Explanation:

You can do this in a one-liner using a command-line XPath tool, such as those mentioned at "https://stackoverflow.com/questions/15461737/how-to-execute-xpath-one-liners-from-shell";. I chose XMLStarlet, but they all have similar syntax.

When parsing a POM, you have to account for namespaces. The docs here helped me figure this out.

In order to get the text for an element in XPath, you use the text() function as explained at https://stackoverflow.com/questions/5033955/xpath-select-text-node.

My POM looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.foo.bar</groupId>
    <artifactId>foobar</artifactId>
    <version>1.0.6-SNAPSHOT</version>
    <packaging>jar</packaging>

The downside here is that if the namespace changes, you have to change the command.

Solution 10 - Maven

Using 'Execute System Groovy Script' as follows:

import jenkins.util.*;
import jenkins.model.*;

def thr = Thread.currentThread();
def currentBuild = thr?.executable;
def projectManager = build.getProject()
def file = projectManager.getWorkspace().child("pom.xml");
def project = new XmlSlurper().parseText(file.readToString())

def param = new hudson.model.StringParameterValue("currentVersion", project.version.toString())
currentBuild.addAction(new hudson.model.ParametersAction(param));

By using Execute System Groovy script you have direct access to the build, from which you can get the project and thus the "child" file in this case pom.xml.

You won't have to create a new file and as you can see it offers very powerful access to every file within the workspace.

Solution 11 - Maven

Based on @Akom`s answer the pre steps to have POM_VERSION are:

  1. "Inject environment variables" with property file your_property_file. Note if you select "Inject environment variables to the build process" the file needs to exist in the jenkins workspace.
  2. run in a pre step execute shell the follwing bash script.

Script

mvn org.apache.maven.plugins:maven-help-plugin:evaluate -Dexpression=project.version -l project_version
# grep for the version pattern rather than not mentioning '\['
echo "POM_VERSION=$(grep -E  '^[0-9.]+(-SNAPSHOT)?$' project_version)" > your_property_file

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionEngineerBetter_DJView Question on Stackoverflow
Solution 1 - MavenNils BreuneseView Answer on Stackoverflow
Solution 2 - MavenEngineerBetter_DJView Answer on Stackoverflow
Solution 3 - MavenAkomView Answer on Stackoverflow
Solution 4 - Mavenapa64View Answer on Stackoverflow
Solution 5 - MavenRoy TrueloveView Answer on Stackoverflow
Solution 6 - MavenSylvainView Answer on Stackoverflow
Solution 7 - MavenJan MView Answer on Stackoverflow
Solution 8 - Mavenjayunit100View Answer on Stackoverflow
Solution 9 - MavenJohn MichelauView Answer on Stackoverflow
Solution 10 - MavenLawrenceMouarkachView Answer on Stackoverflow
Solution 11 - MavenAdamView Answer on Stackoverflow