276

Previous I issued a question on how to change Maven project vesion from command line which lead me to a new issue.

Previously I was able to get the version number since the version was stored as a property that was easy to grep and parse from the command line (bash). Now that the pom.xml <version> element is used for this, it no longer is unique since all the dependencies and maybe some others too use this. I think there is no way to get the current version number with a bash script without external tools for parsing XML or some very context-aware sed command.

The most clean solution in my opinion would be for Maven to hand out this version information. I was thinking of writing a custom maven plugin for retrieving different properties but I thought I'd ask here first.

So, is there any easy way to get the value of ${project.version} to the command line?

Solution

I had to cd to the directory manually but that can be done easily. In my bash script I have:

version=`cd $project_loc && mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | sed -n -e '/^\[.*\]/ !{ /^[0-9]/ { p; q } }'`

Which gives me the current version that I can then advance. Grepping might be simpler but I thought I'd like as robust as possible, so I'm satisfied with the first line that starts with a number and try to handle this as a version number.

# Advances the last number of the given version string by one.
function advance_version () {
    local v=$1
    # Get the last number. First remove any suffixes (such as '-SNAPSHOT').
    local cleaned=`echo $v | sed -e 's/[^0-9][^0-9]*$//'`
    local last_num=`echo $cleaned | sed -e 's/[0-9]*\.//g'`
    local next_num=$(($last_num+1))
    # Finally replace the last number in version string with the new one.
    echo $v | sed -e "s/[0-9][0-9]*\([^0-9]*\)$/$next_num/"
}

And I use this by simply calling:

new_version=$(advance_version $version)
Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
mkko
  • 4,262
  • 3
  • 25
  • 29
  • 1
    The solution seems to miss a ' to finish the sed expression. – nawroth Oct 14 '11 at 12:48
  • Which sed exp? I can't seem to notice. – mkko Oct 14 '11 at 16:17
  • The script starting with "version=`cd $project_loc &&". The ' should be right before the ` at the end of the line. – nawroth Nov 08 '11 at 14:28
  • Fixed that, thank you. I also noticed that the script in our code base doesn't use the -e parameter in the respective part. Unfortunately I can't verify if it's really needed. – mkko Nov 09 '11 at 12:25
  • 1
    make that a mvn -o for faster execution – Nathan Bubna Nov 30 '12 at 22:51
  • 2
    You can replace that complex sed expression with a simple `grep -e '^[[:digit:]]'` – bpedman Sep 14 '13 at 04:14
  • It's been a while but if I recall it right, the purpose of the sed is to strip and later to replace parts of the version string. I don't think you can do this with a single grep. – mkko Sep 17 '13 at 17:53
  • 2
    If you use -o as recommended by @NathanBubna then that will put maven in 'offline' mode. If you don't already have the maven help plugin and dependent jars downloaded then the build will fail. Got burned by that for a bit, hope it helps somebody else. – phillipuniverse Feb 08 '14 at 22:53
  • A simple `sed '/^\[.\+\] /d'` will delete all lines starting with `[...] ` from the output, leaving only the version number (unless there is an error during mvn execution). – Robin479 Oct 28 '15 at 12:19
  • Alternatively, `sed '/^[0-9]\+\./!d'` or `grep '^[0-9]\+\.'` will filter all lines not starting with ``, which includes sneaky lines like `Downloading: \n3/9 KB\r6/9 KB\r9/9 KB\rDownloaded: `, where the line starts with `3/9 KB ...` but is outputted as `Downloaded: ...`. – Robin479 Oct 28 '15 at 13:18
  • 1
    before you start hating maven, read [this answer](https://stackoverflow.com/a/50613762/1059372) – Eugene Mar 27 '19 at 15:27

33 Answers33

319

The Maven Help Plugin is somehow already proposing something for this:

  • help:evaluate evaluates Maven expressions given by the user in an interactive mode.

Here is how you would invoke it on the command line to get the ${project.version}:

mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate \
    -Dexpression=project.version

As noted in the comments by Seb T, to only print the version without the maven INFO logs, additionally use -q -DforceStdout:

mvn help:evaluate -Dexpression=project.version -q -DforceStdout
ryenus
  • 15,711
  • 5
  • 56
  • 63
Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
  • Great, thank you! Now one last issue for me is how should I get the version of a certain child project? I tried setting the `artifact` property, but it seems to give me `LATEST`. – mkko Aug 23 '10 at 09:00
  • @mkko: Do you mean, how to get the version of a specific child when running maven from an aggregating parent? – Pascal Thivent Aug 23 '10 at 09:08
  • @pascal Yes. I understand I could just `cd` and run maven there but changing directories in a script is not nice, at least in this case. – mkko Aug 23 '10 at 09:11
  • @mkko: Yes, I understand too :) I just wanted to get confirmation. But I have to think a bit (and I'm not sure I'll find a nice solution). – Pascal Thivent Aug 23 '10 at 10:04
  • @mkko: I didn't find a solution to "query" the child modules from the parent. And I don't know how to skip the `[INFO]` stuff so I'm afraid you'll have to grep what you want from the script. – Pascal Thivent Aug 24 '10 at 15:38
  • Fine to find [INFO] messages are anoying for others too, I use mvn help:evaluate -Dexpression=project.basedir | grep -v '^\[INFO\]' – albfan Feb 19 '12 at 12:33
  • 86
    I'm removing all logging (INFO,WARNING,etc) and 'Download' messages with `mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version|grep -Ev '(^\[|Download\w+:)'` – Chadwick Mar 29 '13 at 18:58
  • 4
    You might want to also add `2> /dev/null` as otherwise you can get `Picked up _JAVA_OPTIONS:` – Jakub Bochenski Nov 02 '15 at 21:06
  • 27
    Here's an approach I favor: `printf 'VERSION=${project.version}\n0\n' | mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate | grep '^VERSION'` – ash Jul 01 '16 at 17:47
  • Additional suggestion so that this also works with a clean environment, for instance in a (dynamically created) jenkins slave: – Ivin Dec 11 '16 at 20:51
  • 2
    To filter out everything except for the version, this works for me: `mvn help:evaluate -Dexpression=project.version | grep -e '^[^\[]'` – mturatti Jan 01 '17 at 16:50
  • additionally if you want to build on @ash you can add `export` and then backticks (`) around their expression to make it set your environment variable to that – hdost Jun 02 '17 at 15:07
  • 3
    Based on previous answers, this gives a clean answer: `printf 'VERSION=${project.version}' | mvn help:evaluate | grep '^VERSION=' | sed 's/^VERSION=//g'` – yinon Oct 26 '17 at 08:39
  • I had to modify the grep from @Chadwick slightly to include whitespace at the beginning, as some WARNING messages were getting printed with a carriage return (ascii 13): `mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -Ev '(^\s*\[|Download\w+:)'` – haridsv Nov 14 '17 at 10:35
  • @Chadwick solution is broken with Maven 3.5.2, due to MNG-5457. This solution is by nature fragile due to the dependency on Maven log output. – Julien H. - SonarSource Team Jan 08 '18 at 13:00
  • 91
    @montoyaed posted the [best answer](https://stackoverflow.com/a/50613762/5116073) which simply is `mvn help:evaluate -Dexpression=project.version -q -DforceStdout`. To capture it in a variable in Bash use `version=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)` – Seb T Jun 11 '18 at 19:18
  • 1
    @Chadwick I figured that you also need to enable batch mode with maven `-B` option, or `"Downloaded"` lines don't get filtered. – haridsv Aug 07 '18 at 12:05
  • 4
    I'm not sure the `-q` option suddenly hides all including the expression result. – Jin Kwon Feb 11 '20 at 04:27
  • do this to get only the version `mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | tail -n 8 | head -n 1` – robert.baboi Oct 12 '20 at 18:53
257

Tom's solution with the Exec Maven Plugin is much better, but still more complicated than it needs to be. For me it's as simple as:

MVN_VERSION=$(mvn -q \
    -Dexec.executable=echo \
    -Dexec.args='${project.version}' \
    --non-recursive \
    exec:exec)
Clay
  • 319
  • 2
  • 15
rjrjr
  • 3,892
  • 1
  • 22
  • 18
  • 35
    I think this is the easiest way since it does not imply use of grep or similar things. Quick note: you may make it a bit shorter: `mvn -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive exec:exec` – scrutari Sep 13 '16 at 16:57
  • 1
    This solution worked well for me as I wanted to print groupId, artifactId and version.. `-Dexec.args='${project.groupId}:${project.artifactId}:${project.version}'`. – James H. Jan 05 '17 at 16:03
  • 1
    `[ERROR] Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.3.2:exec (default-cli) on project audit-events-processor-parent: Command execution failed. Cannot run program "maven" (in directory "/tmp"): error=2, No such file or directory` *shrug* yet another answer that doesn't work for me, oh well – cbmanica Jan 31 '17 at 20:03
  • Thank you this is the best solution I have seen so far, since it does not require to apply fragile grep/sed commands or similar – Mike76 Aug 16 '17 at 07:55
  • What is `set -o errexit` – theonlygusti Nov 06 '18 at 15:05
  • You may want to add ` – Piotr Findeisen Nov 28 '18 at 12:47
  • I've tried this approach and the `help:evaluate` approach, and for my project the difference is that `exec:exec` is 1.5 second slower than `help:evaluate`. Just testing for a single variable (`project.version`), no complex expression, in a multi-module setup without the `--non-recursive` flag (tried with this flag in my root reactor and the results were messy) – Jefferson Quesado Nov 13 '19 at 13:38
  • Hi! I'm quite new to this. How did you specify the plugin using this command? Is it something like this? org.codehaus.mojo exec-maven-plugin 3.0.0 What execution should I put in it? – Loren Jan 14 '22 at 01:10
  • That's exactly what I needed, assign the version to a variable and to use it later on in a pipeline. Thanks! – Joselo Apr 28 '22 at 08:33
140

After doing some research I found the following:

  1. Maven has been blamed because integration with DevOps tools is not easy due to the fact that it does not follow some good practices regarding CLI tools, i.e:

http://www.faqs.org/docs/artu/ch01s06.html (not available anymore) "The Unix Way" (ii) Expect the output of every program to become the input of another, as yet unknown, program. Don't clutter output with extraneous information. Avoid stringently columnar or binary input formats. Don't insist on interactive input. What does it actually mean? Your output should be:

  • "grepable": (One "record" per line)
  • "cutable": (Delimited "fields")
  • exit codes: 0 for success, nonzero for failure.
  • messaging (stderr) vs. output (stdout)

(ref: Make awesome command line apps with ruby by Dave Copeland Jan 18, 2012 https://youtu.be/1ILEw6Qca3U?t=372)

  1. Honesty I think Dave Copeland was right when he said that maven does't play fairly with others. So I decided to give a look to maven's source code as well as to maven-help-plugin's source code as well. It seems that they have fixed a little bit the maven's -q switch (I was using version 3.5.3 at that time), so now if you pass it, you won't get all the annoying non-sense logging stuff that prevents maven from being used within automated scripts. So you should be able to use something like this:

    mvn help:evaluate -Dexpression=project.version -q
    

The problem is that this command prints nothing because by default the help plugin outputs through the logger which has been silenced by the -q switch. (latest available version of the plugin at that time was 3.1.0 released on June, 3rd 2018)

  1. Karl Heinz Marbaise (https://github.com/khmarbaise) fixed it by adding an optional parameter that allows you to call it in the following way:

    mvn help:evaluate -Dexpression=project.version -q -DforceStdout
    

The commit description is available at: (https://github.com/apache/maven-help-plugin/commit/316656983d780c04031bbadd97d4ab245c84d014)

Again, you should always verify the exit code of the command and redirect all stderr to /dev/null on unix.

Eduardo Montoya
  • 1,520
  • 2
  • 12
  • 14
  • 2
    This would be my preferred solution and is also mentioned on the official [help pages](https://maven.apache.org/plugins/maven-help-plugin/evaluate-mojo.html). However, it doesn't work for me. I am on MacOS with Maven v3.5.3. When I don't use the `-q` switch it prints out the version correctly (in between the log lines). Any ideas? – gucce Jul 12 '18 at 12:23
  • 3
    This should be the accepted answer. It works in Windows and Linux (I didn't try Max OSX), and it's simple. Thank you. – trash80 Jul 24 '18 at 18:10
  • 1
    @montoyaedu Sorry for not responding. In the meantime I have updated to maven 3.5.4 which works fine with the `-q` switch. – gucce Oct 10 '18 at 08:58
  • 2
    @gucce I can confirm that maven version used affects this: with 3.5.2 (package version on debian 9) the output with `-q -DforceStdout` was empty, even ensuring version 3.1.0 of the plugin was used with pluginManagement) ; i configured maven wrapper with version 3.5.4 of maven, and it worked correctly – Gorkk Oct 26 '18 at 16:29
  • 4
    Finally, a practical solution without grep for 2019 - (this should become the accepted answer). Works with [CI-friendly versions](https://maven.apache.org/maven-ci-friendly.html) too - tested on 3.3.9, 3.5.3, 3.5.4, 3.6.0 – Ed Randall Mar 11 '19 at 08:37
  • 1
    Add `-o` to run offline maven (a little bit faster): `mvn help:evaluate -Dexpression=project.version -q -o -DforceStdout` - but make sure you already have in local repo the evaluate plugin and all required dependencies – user1053510 Apr 12 '19 at 12:13
  • 1
    u need to make sure that the help plugin is at least version 3.1.0. For me it had little to do with the maven version itself but with the spring boot parent pom, so i had to overwrite the version! – elonderin Apr 22 '19 at 15:21
  • 1
    Works for me on Mac. Apache Maven 3.5.4 - OS name: "mac os x", version: "10.14.5", arch: "x86_64", family: "mac" – Didier Breedt Jun 03 '19 at 09:57
  • 1
    Do you know of a way to make this command run faster? Even with -o this is taking ~2 minutes on my build agent. – Sloloem Nov 06 '19 at 16:46
53

This is the cleanest solution there is:

mvn org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \
-Dexpression=project.version -q -DforceStdout

Advantages:

  • This works fine on all operating systems and all shells.
  • No need for any external tools!
  • [important] This works even if project version is inherited from parent pom.xml

Note:

  • maven-help-plugin version 3.2.0 (and above) has forceStdout option. You may replace 3.2.0 in above command with a newer version from the list of available versions of mvn-help-plugin from artifactory, if available.
  • Option -q suppresses verbose messages ([INFO], [WARN] etc.)

Alternatively, you can add this entry in your pom.xml, under plugins section:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-help-plugin</artifactId>
    <version>3.2.0</version>
</plugin>

and then run above command compactly as follows:

mvn help:evaluate -Dexpression=project.groupId -q -DforceStdout

If you want to fetch groupId and artifactId as well, check this answer.

Manu Manjunath
  • 6,201
  • 3
  • 32
  • 31
  • 7
    This is IMHO the best answer as all the others failed to point out (as I found out the hard way) that you need at least version 3.1.0 of the maven-help-plugin because otherwise the -DforceStdout option [will be unknown](https://issues.apache.org/jira/browse/MPH-144) and running "mvn -q help:evaluate ...." will produce no output at all. – Tobias Gierke Apr 21 '21 at 07:18
52
mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -v '\['
palacsint
  • 28,416
  • 10
  • 82
  • 109
user1712021
  • 557
  • 4
  • 3
50

Why not use the right tool for the job? Using xpath syntax is the best approach to retrieving the version number, since it is the intended method of accessing a XML data structure. The expression below is traversing the pom using the "local name" of the elements, in other words ignoring namespace declarations which may or may not be present in the xml.

xmllint --xpath "//*[local-name()='project']/*[local-name()='version']/text()" pom.xml
redseven
  • 849
  • 6
  • 11
lukeforehand
  • 750
  • 6
  • 11
  • @bobmarksie I second that; using maven and scrubbing the output with regexp's is painful. – mhvelplund Jun 13 '18 at 06:52
  • 4
    What about a project that inherits from a parent pom. – Wes Jun 15 '18 at 11:53
  • 6
    "Why not use the right tool for the job?" IE !Maven? – jeremyjjbrown Jun 18 '18 at 15:47
  • I understand that using `mvn` is the right approach and `exec` plugin actually works nicely, but all mvn solutions do have to resolve and I am trying to bootstrap a build pipeline where dependency resolution will not work, so I am going to replace the `exec` approach with this solution. Luckily, I don't have to worry about versions inherited from parents. – haridsv Feb 01 '19 at 16:21
  • 3
    This won't work with ci-friendly versioning, where the version is a property like `${revision}` for example. Ref. https://maven.apache.org/maven-ci-friendly.html – Ed Randall Mar 11 '19 at 08:29
  • Doesn't work on windows git bash + relying on a new tool different than maven when we don't need is not a good practice. – pdem Apr 05 '19 at 10:42
  • I think that this is the best approach when you are dealing with older versions of maven (due to old jdk). – Pedro Pinheiro Jun 01 '20 at 19:22
  • This is more suitable for interactive use due to its speed. And I'd say using an xml parser to parse a maven xml is still correct tooling. – DieterDP Dec 20 '21 at 16:05
35

This will avoid the need for grepping off log entries from the output:

mvn -Dexec.executable='echo' -Dexec.args='${project.version}' --non-recursive exec:exec -q
approxiblue
  • 6,982
  • 16
  • 51
  • 59
Jose Alban
  • 7,286
  • 2
  • 34
  • 19
  • While this code may answer the question, providing additional context regarding _why_ and/or _how_ it answers the question would significantly improve its long-term value. Please [edit] your answer to add some explanation. – Toby Speight Apr 12 '16 at 13:02
  • 1
    I think for this approach it is necessary to put the "-q" after mvn. – Rudge Aug 07 '17 at 19:47
  • This is better than the accepted solution; no need to filter out maven noisy output. – Willian Mitsuda Jun 20 '18 at 03:17
19
python -c "import xml.etree.ElementTree as ET; \
  print(ET.parse(open('pom.xml')).getroot().find( \
  '{http://maven.apache.org/POM/4.0.0}version').text)"

As long as you have python 2.5 or greater, this should work. If you have a lower version than that, install python-lxml and change the import to lxml.etree. This method is quick and doesn't require downloading any extra plugins. It also works on malformed pom.xml files that don't validate with xmllint, like the ones I need to parse. Tested on Mac and Linux.

pdr
  • 360
  • 2
  • 6
13

I kept running into side cases when using some of the other answers here, so here's yet another alternative.

version=$(printf 'VER\t${project.version}' | mvn help:evaluate | grep '^VER' | cut -f2)
slow
  • 810
  • 9
  • 14
11

There is also one option without need Maven:

grep -oPm1 "(?<=<version>)[^<]+" "pom.xml"
Michal Sipek
  • 536
  • 1
  • 6
  • 23
  • This one shows only the first occurrence in pom. In my case first occurrence gives parent pom version. But to be honest this is the answer I was looking for. It's much faster than solutions mentioned earlier and it's easy to modify it in order to get proper occurrence. In order to get second occurrence use: `grep -oPm2 "(?<=)[^<]+" pom.xml | sed -n 2p` In order to get third occurrence use: `grep -oPm3 "(?<=)[^<]+" pom.xml | sed -n 3p` and so on – Krzysztof Cieśliński Jan 14 '20 at 10:42
  • 1
    You are assuming the version element is the first occurrence, and it does not work when the assumption is invalid. – devildelta Jun 05 '20 at 08:50
11

This is by far the easiest bash cut and paste solution:

VERSION=$(mvn exec:exec -Dexec.executable='echo' -Dexec.args='${project.version}' --non-recursive -q)
echo $VERSION

it echoes

1.4
freedev
  • 25,946
  • 8
  • 108
  • 125
7

If you don't mind to write the version into a temporary file, there is another solution (without grep/sed) that works well for me. (EDIT: see rjrjr's answer for a much simpler solution without any temporary file hassle)

I use the Exec Maven Plugin along with the echo binary. In contrast to the Maven Help Plugin, the Exec Plugin allows output redirection into a file, which can be used to bypass grep/sed, and makes it even possible to parse strange things like multiline version strings (with CDATA block in version tag), at least to a certain extent.

#!/usr/bin/env sh

MVN_VERSION=""
VERSION_FILE=$( mktemp mvn_project_version_XXXXX )
trap "rm -f -- \"$VERSION_FILE\"" INT EXIT

mvn -Dexec.executable="echo" \
    -Dexec.args='${project.version}' \
    -Dexec.outputFile="$VERSION_FILE" \
    --non-recursive \
    --batch-mode \
    org.codehaus.mojo:exec-maven-plugin:1.3.1:exec > /dev/null 2>&1 ||
    { echo "Maven invocation failed!" 1>&2; exit 1; }

# if you just care about the first line of the version, which will be
# sufficent for pretty much every use case I can imagine, you can use
# the read builtin
[ -s "$VERSION_FILE" ] && read -r MVN_VERSION < "$VERSION_FILE"

# Otherwise, you could use cat.
# Note that this still has issues when there are leading whitespaces
# in the multiline version string
#MVN_VERSION=$( cat "$VERSION_FILE" )

printf "Maven project version: %s\n" "$MVN_VERSION"
Tom
  • 515
  • 7
  • 9
  • 7
    This is a much better solution than the helper plugin, and you don't need all that i/o. Just add a -q flag and the only output will be the version. So: mvn -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.3.1:exec – rjrjr Oct 22 '14 at 17:51
  • rjrjr: Great! The only thing I need to mention here is error handling: If mvn fails, you get an invalid version string. So some validation is required, like checking mvn return code or the string itself. – Tom Oct 23 '14 at 06:19
6

Just for the record, it's possible to configure Maven's Simple SLF4J logging directly in the command line to output only what we need by configuring:

  • org.slf4j.simpleLogger.defaultLogLevel=WARN and
  • org.slf4j.simpleLogger.log.org.apache.maven.plugins.help=INFO

as documented at http://www.slf4j.org/api/org/slf4j/impl/SimpleLogger.html

MAVEN_OPTS="\
-Dorg.slf4j.simpleLogger.defaultLogLevel=WARN \
-Dorg.slf4j.simpleLogger.log.org.apache.maven.plugins.help=INFO" \
mvn help:evaluate -o -Dexpression=project.version

As a result, one can run simply tail -1 and get:

$ MAVEN_OPTS="\
-Dorg.slf4j.simpleLogger.defaultLogLevel=WARN \
-Dorg.slf4j.simpleLogger.log.org.apache.maven.plugins.help=INFO" \
mvn help:evaluate -o -Dexpression=project.version | tail -1

1.0.0-SNAPSHOT

Note that this is a one-liner. MAVEN_OPTS are being rewritten only for this particular mvn execution.

Stepan Vavra
  • 3,884
  • 5
  • 29
  • 40
5

I noticed some spurious Downloaded: lines coming in the output that were breaking my original assignment. Here's the filter I've settled on; hope it helps!

version=$(mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | egrep -v '^\[|Downloading:' | tr -d ' \n')

EDIT

Not 100% sure why, but when running this through a post-build script in Jenkins, the output was coming out as [INFO]version, e.g. [INFO]0.3.2.

I dumped the output to a file and ran it through my first filter directly from BASH, it works fine.., so again, unsure what's going on in Jenkins land.

To get it 100% in Jenkins, I've added a follow-up sed filter; here's my latest

version=$(mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | egrep -v '^\[|Downloading:' | tr -d ' \n' | sed -E 's/\[.*\]//g')

EDIT

One last note here.. I found out tr was still resulting in things like /r/n0.3.2 (again only when running via Jenkins). Switched to awk and the problem has gone away! My final working result

mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version \
| egrep -v '^\[|Downloading:' | sed 's/[^0-9\.]//g' | awk 1 ORS=''
quickshiftin
  • 66,362
  • 10
  • 68
  • 89
5

I've recently developed the Release Candidate Maven plugin that solves this exact problem so that you don't have to resort to any hacky shell scripts and parsing the output of the maven-help-plugin.

For example, to print the version of your Maven project to a terminal, run:

mvn com.smartcodeltd:release-candidate-maven-plugin:LATEST:version

which gives output similar to maven-help-plugin:

[INFO] Detected version: '1.0.0-SNAPSHOT'
1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

However, you can also specify an arbitrary output format (so that the version could be picked up from the log by a CI server such as TeamCity):

mvn com.smartcodeltd:release-candidate-maven-plugin:LATEST:version \
   -DoutputTemplate="##teamcity[setParameter name='env.PROJECT_VERSION' value='{{ version }}']"

Which results in:

[INFO] Detected version: '1.0.0-SNAPSHOT'
##teamcity[setParameter name='env.PROJECT_VERSION' value='1.0.0-SNAPSHOT']
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

To save the output to a file (so that a CI server such as Jenkins could use it):

mvn com.smartcodeltd:release-candidate-maven-plugin:LATEST:version \
   -DoutputTemplate="PROJECT_VERSION={{ version }}" \
   -DoutputUri="file://\${project.basedir}/version.properties"

The resulting version.properties file will look as follows:

PROJECT_VERSION=1.0.0-SNAPSHOT

On top of all the above, Release Candidate also allows you to set the version of your project (which is something you'd probably do on your CI server) based on the API version you've defined in your POM.

If you'd like to see an example of Release Candidate being used as part of the Maven lifecycle, have a look at the pom.xml of my other open-source project - Build Monitor for Jenkins.

approxiblue
  • 6,982
  • 16
  • 51
  • 59
Jan Molak
  • 4,426
  • 2
  • 36
  • 32
5

A simple maven only solution

mvn -q -N org.codehaus.mojo:exec-maven-plugin:1.3.1:exec \
    -Dexec.executable='echo' \
    -Dexec.args='${project.version}'

And for bonus points parsed part of a version

mvn -q -N org.codehaus.mojo:build-helper-maven-plugin:3.0.0:parse-version \
    org.codehaus.mojo:exec-maven-plugin:1.3.1:exec \
    -Dexec.executable='echo' \
    -Dexec.args='${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}'
Jakob O.
  • 334
  • 4
  • 5
4

The easy to understand all-in-one solution that outputs the maven project version, and suppresses extraneous output from [INFO] and Download messages:

mvn -o org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -v '\['

Same thing, but split onto two lines:

mvn -o org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate \
      -Dexpression=project.version | grep -v '\['

Outputs: 4.3-SNAPSHOT

So, using your project.version in a simple bash script:

projectVersion=`mvn -o org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -v '\['`
cd "target/"$projectVersion"-build"

Other solutions on this page didn't seem to combine all the tricks into one.

Peter Dietz
  • 2,599
  • 1
  • 24
  • 23
4

This worked for me, offline and without depending on mvn:

VERSION=$(grep --max-count=1 '<version>' <your_path>/pom.xml | awk -F '>' '{ print $2 }' | awk -F '<' '{ print $1 }')
echo $VERSION
George
  • 6,006
  • 6
  • 48
  • 68
4

I found right balance for me. After mvn package maven-archiver plugin creates target/maven-archiver/pom.properties with contents like this

version=0.0.1-SNAPSHOT
groupId=somegroup
artifactId=someArtifact

and I am using bash just to execute it

. ./target/maven-archiver/pom.properties

then

echo $version
0.0.1-SNAPSHOT

Of course this is not safe at all to execute this file, but execution can easily be converted into perl or bash script to read and set environment variable from that file.

Vladimir I
  • 111
  • 2
  • 5
3

Should be easier since this bug is fixed in maven-help-plugin 3.0.0: MPH-99 Evaluate has no output in quiet mode.

approxiblue
  • 6,982
  • 16
  • 51
  • 59
mturra
  • 640
  • 8
  • 14
2

Add the following plugin to your pom.xml

    ...
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-help-plugin</artifactId>
        <version>3.2.0</version>
        <executions>
            <execution>
                <id>generate-version-file</id>
                <phase>prepare-package</phase>
                <goals>
                    <goal>evaluate</goal>
                </goals>
                <configuration>
                    <expression>project.version</expression>
                    <output>${project.build.directory}/version.txt</output>
                </configuration>
            </execution>
        </executions>
    </plugin>
    ...

This will generate a target/version.txt file as a normal part of your build.

All you then need to do to get this to the shell is the following:

#!/bin/sh
value=`cat target/version.txt`
echo "$value"
#!/bin/bash
value=$(<target/version.txt)
echo "$value"
Marv
  • 3,517
  • 2
  • 22
  • 47
1

Exec plugin works without any output parsing because output can be redirected into file and injected back into the job environment via EnvInject plugin:

enter image description here

1

Either you have mvn give you the answer (as most answers suggest), or you extract the answer from the pom.xml. The only drawback of the second approach is that you can very easily extract the value of the <version/> tag, but it will be meaningful only if it's literal, that is, not a Maven property. I chose this approach anyway because:

  • mvn is way to verbose and I simply don't like filtering its output.
  • Starting mvn is very slow compared to reading the pom.xml.
  • I always use literal values in <version/>.

mvn-version is a zsh shell script that uses xmlstarlet to read the pom.xml and print the version of the project (if it exists) or the version of the parent project (if it exists):

$ mvn-version .
1.0.0-SNAPSHOT

The advantage is that it's way quicker than running mvn:

$ time mvn-version .
1.1.0-SNAPSHOT
mvn-version .  0.01s user 0.01s system 75% cpu 0.019 total

$ time mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate \
> -Dexpression=project.version
mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate   4.17s user 0.21s system 240% cpu 1.823 total

The difference on my machine is greater than two orders of magnitude.

Enrico M. Crisostomo
  • 1,653
  • 1
  • 17
  • 26
1

Base on the question, I use this script below to automatic increase my version number in all maven parent/submodules:

#!/usr/bin/env bash  

# Advances the last number of the given version string by one.  
function advance\_version () {  
    local v=$1  
    \# Get the last number. First remove any suffixes (such as '-SNAPSHOT').  
  local cleaned=\`echo $v | sed \-e 's/\[^0-9\]\[^0-9\]\*$//'\`  
 local last\_num=\`echo $cleaned | sed \-e 's/\[0-9\]\*\\.//g'\`  
 local next\_num=$(($last\_num+1))  
  \# Finally replace the last number in version string with the new one.  
  echo $v | sed \-e "s/\[0-9\]\[0-9\]\*\\(\[^0-9\]\*\\)$/$next\_num/"  
}  

version=$(mvn org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout)  

new\_version=$(advance\_version $version)  

mvn versions:set -DnewVersion=${new\_version} -DprocessAllModules -DgenerateBackupPoms=false
Yu Jiaao
  • 4,444
  • 5
  • 44
  • 57
1

Quickest way that gets you just the text without all the trimmings

mvn help:evaluate -q -DforceStdout -D"expression=project.version"
Max Barrass
  • 2,776
  • 1
  • 19
  • 10
0

this is an edit from above

cat pom.xml | grep "" | head -n 1 | sed -e "s/version//g" | sed -e "s/\s*[<>/]*//g"

I tested it out on on the cmdline works well

grep "" pom.xml | head -n 1 | sed -e "s/version//g" | sed -e "s/\s*[<>/]*//g"

is another version of the same. I have a need to get the version number in Jenkins CI in k8s without mvn installed so this is most helpful

thanks all.

Philip Ruff
  • 11
  • 1
  • 3
  • What if you have a parent POM? What if the dependencies are unusually placed before the project's GAV? – ingyhere Sep 02 '20 at 07:23
0

I need exactly this requirement during my Travis job but with multiple values. I start with this solution but when calling multiple time this is very slow (I need 5 expresions).

I wrote a simple maven plugin to extract pom.xml's values into .sh file.

https://github.com/famaridon/ci-tools-maven-plugin

mvn com.famaridon:ci-tools-maven-plugin:0.0.1-SNAPSHOT:environment -Dexpressions=project.artifactId,project.version,project.groupId,project.build.sourceEncoding

Will produce that:

#!/usr/bin/env bash
CI_TOOLS_PROJECT_ARTIFACTID='ci-tools-maven-plugin';
CI_TOOLS_PROJECT_VERSION='0.0.1-SNAPSHOT';
CI_TOOLS_PROJECT_GROUPID='com.famaridon';
CI_TOOLS_PROJECT_BUILD_SOURCEENCODING='UTF-8';

now you can simply source the file

source .target/ci-tools-env.sh

Have fun.

0

One alternative would be to parse with yq (https://github.com/kislyuk/yq) like so:

cat pom.xml | xq -r '.project.version'

Notice the executable is xq not yq

To get xq, install yq like so pip install yq

robert.baboi
  • 354
  • 1
  • 5
0

In docker containers with only busybox available I use awk.

version=$(
 awk '
  /<dependenc/{exit}
  /<parent>/{parent++};
  /<version>/{
    if (parent == 1) {
      sub(/.*<version>/, "");
      sub(/<.*/, "");
      parent_version = $0;
    } else {
      sub(/.*<version>/, "");
      sub(/<.*/, "");
      version = $0;
      exit
    }
  }
  /<\/parent>/{parent--};
  END {
    print (version == "") ? parent_version : version
  }' pom.xml
)

Notes:

  • If no artifact version is given parent version is printed instead.
  • Dependencies are required to come after artifact and parent version. (This could be overcome quite easily but I don't need it.)
vboerchers
  • 767
  • 1
  • 6
  • 16
-1
mvn help:evaluate -Dexpression=project.version | sed -e 1h -e '2,3{H;g}' -e '/\[INFO\] BUILD SUCCESS/ q' -e '1,2d' -e '{N;D}' | sed -e '1q'

I'm just adding small sed filter improvement I have recently implemented to extract project.version from maven output.

Gábor Lipták
  • 9,646
  • 2
  • 59
  • 113
  • Maven command works for me but sed doesn't `sed: 1: "2,3{H;g}` `": extra characters at the end of g command` – byxor Feb 07 '22 at 11:19
-1

I am using a one-liner in my unix shell ...

cat pom.xml | grep "" | head -n 1 | sed -e "s/version//g" | sed -e "s/\s*[<>/]*//g"

You can hide this line in a shell script or as an alias.

-2
VERSION=$(head -50 pom.xml | awk -F'>' '/SNAPSHOT/ {print $2}' | awk -F'<' '{print $1}')

This is what I used to get the version number, thought there would have been a better maven way to do so

Tristik
  • 17
  • 4
-2
VERSION=$(mvn -version | grep 'Apache Maven' | grep -o '[0-9].[0-9].[0-9]')
echo $VERSION
skyho
  • 1,438
  • 2
  • 20
  • 47
  • 1
    The question is about getting the Maven project version, not the version of Maven itself. – Jaap Sep 19 '22 at 13:49