Как получить версию проекта Maven в командной строке bash

Предыдущее Я выпустил вопрос о о том, как изменить проект Maven vesion из командной строки, что приведет меня к новой проблеме.

Раньше мне удалось получить номер версии, поскольку версия была сохранена как свойство, которое было легко grep и проанализировать из командной строки (bash). Теперь, когда элемент pom.xml используется для этого, он больше не уникален, так как все зависимости и, возможно, некоторые другие тоже используют это. Я думаю, что нет способа получить текущий номер версии с помощью bash script без внешних инструментов для синтаксического анализа xml или некоторой команды sed с поддержкой контекста.

Самым чистым решением в моем мнении было бы для Maven передать эту информацию о версии. Я подумывал написать собственный плагин maven для извлечения разных свойств, но я подумал, что сначала попрошу.

Итак, есть ли простой способ получить значение ${project.version} в командной строке? Спасибо заранее.

Решение

Спасибо за помощь. Я должен был cd в каталог вручную, но это можно сделать легко. В моем bash script у меня есть

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 } }'`

Что дает мне текущую версию, которую я могу продвинуть. Греппинг может быть проще, но я думал, что мне будет как можно более надежно, поэтому я доволен первой строкой, которая начинается с числа и пытается обрабатывать это как номер версии.

# 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/"
}

И я использую это, просто позвонив

new_version=$(advance_version $version)

Надеюсь, это поможет кому-то.

Ответ 1

Плагин поддержки Maven как-то уже предлагает что-то для этого:

  • help:evaluate оценивает выражения Maven, заданные пользователем в интерактивном режиме.

Вот как вы могли бы вызвать его в командной строке, чтобы получить ${project.version}:

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

Ответ 2

Решение Tom с плагином Exec Maven намного лучше, но все же сложнее, чем нужно. Для меня это так просто, как:

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

Ответ 3

Я провел некоторые исследования и обнаружил следующее:

  1. Maven обвиняют в том, что он не может быть легко интегрирован в сценарии работы системы, поскольку он не следует некоторым рекомендациям относительно инструментов CLI. (ссылка: https://youtu.be/1ILEw6Qca3U?t=372)

  2. Вдохновленный предыдущим утверждением, я решил взглянуть на исходный код maven, а также на плагин maven-help-plugin. Кажется, что они немного исправили переключатель maven -q (я использую версию 3.5.3), так что теперь, если вы пропустите его, вы не получите все раздражающие средства регистрации, не связанные со смыслом, которые не позволяют maven быть используется в автоматизированных сценариях. Таким образом, вы должны быть в состоянии использовать что-то вроде этого:

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

    Проблема в том, что эта команда ничего не печатает, потому что по умолчанию плагин справки выводится через регистратор, который был отключен переключателем -q. (последняя доступная версия плагина - 3.1.0, выпущенная 3 июня 2018 г.)

  3. Карл Хайнц Марбез (https://github.com/khmarbaise) исправил это, добавив необязательный параметр, который позволяет вызывать его следующим образом:

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

    Описание фиксации доступно по адресу: (https://github.com/apache/maven-help-plugin/commit/316656983d780c04031bbadd97d4ab245c84d014)

Ответ 4

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

Ответ 5

Самый верный ответ - довольно мусор, на мой взгляд, вы должны использовать кучу grep, чтобы взломать вывод консоли maven. Почему бы не использовать правильный инструмент для работы? Использование синтаксиса xpath - лучший способ получить номер версии, поскольку это предназначенный метод доступа к структуре данных XML. Выражение, приведенное ниже, пересекает pom, используя "локальное имя" элементов, другими словами, игнорируя объявления пространств имен, которые могут быть или не быть в xml.

xmllint --xpath "//*[local-name()='project']/*[local-name()='version']/text()" pom.xml

Ответ 6

Это позволит избежать необходимости отключать записи журнала на выходе:

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

Ответ 7

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)"

Пока у вас есть python 2.5 или выше, это должно работать. Если у вас более низкая версия, установите python-lxml и измените импорт на lxml.etree. Этот метод является быстрым и не требует загрузки каких-либо дополнительных плагинов. Он также работает с malformed файлами pom.xml, которые не проверяются с помощью xmllint, как те, которые мне нужны для синтаксического анализа. Протестировано на Mac и Linux.

Ответ 8

Я продолжал сталкиваться с побочными случаями при использовании некоторых других ответов здесь, так что вот еще одна альтернатива.

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

Ответ 9

Это самое чистое решение, которое я нашел:

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

Преимущества:

  • Это прекрасно работает во всех операционных системах
  • Нет необходимости в каких-либо внешних инструментах!

Примечание:

  • Опция -q подавляет подробные сообщения.
  • maven-help-plugin версия 3.2.0 (и выше) имеет опцию forceStdout. Вы можете заменить 3.2.0 в вышеприведенной команде новой версией из списка доступных версий mvn-help-plugin из артефакта, если он доступен.

Ответ 10

Если вы не хотите писать версию во временный файл, есть еще одно решение (без grep/sed), которое хорошо работает для меня. ( EDIT: см. rjrjr answer для гораздо более простого решения без каких-либо временных сбоев файлов)

Я использую Exec Maven Plugin вместе с двоичным кодом echo. В отличие от плагина Maven Help плагин Exec позволяет перенаправить перенаправление вывода в файл, который можно использовать для обхода grep/sed, а также позволяет анализировать такие странные вещи, как многострочные строки строк (с блоком CDATA в теге версии) по крайней мере, в определенной степени.

#!/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"

Ответ 11

Только для записи можно настроить ведение журнала Maven Simple SLF4J непосредственно в командной строке для вывода только того, что нам нужно, настроив:

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

как описано в 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

В результате можно просто запустить tail -1 и получить:

$ 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

Обратите внимание, что это однострочный. MAVEN_OPTS переписываются только для этого конкретного выполнения mvn.

Ответ 12

Я заметил некоторые паразитные строки Downloaded:, идущие на выходе, которые нарушали мое первоначальное назначение. Здесь фильтр, на котором я остановился; надеюсь, что это поможет!

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

ИЗМЕНИТЬ

Не уверенно, что 100%, но при запуске через пост-сборку script в Jenkins выход выходил как [INFO]version, например. [INFO]0.3.2.

Я вынул вывод в файл и пропустил его через свой первый фильтр непосредственно из BASH, он отлично работает.., так что опять же, не зная, что происходит на земле Дженкинса.

Чтобы получить 100% в Jenkins, я добавил следующий фильтр sed; здесь мой последний

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')

ИЗМЕНИТЬ

Одна последняя заметка здесь. Я узнал, что tr все еще приводил к вещам вроде /r/n0.3.2 (снова только при запуске через Jenkins). Переключился на awk, и проблема исчезла! Мой последний рабочий результат

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=''

Ответ 13

Простое решение maven

mvn -q -N org.codehaus.mojo:exec-maven-plugin:1.3.1:exec \
    -Dexec.executable='echo' \
    -Dexec.args='${project.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}'

Ответ 14

Недавно я разработал Release Candidate Плагин Maven, который решает эту проблему, t нужно прибегать к любым скриптам хакерской оболочки и анализировать выходные данные maven-help-plugin.

Например, чтобы напечатать версию вашего проекта Maven на терминал, запустите:

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

который дает результат, похожий на maven-help-plugin:

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

Однако вы также можете указать произвольный формат вывода (чтобы версия могла быть выбрана из журнала сервером CI, например TeamCity):

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

Результат:

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

Чтобы сохранить вывод в файл (чтобы сервер CI, такой как Jenkins, мог использовать его):

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

Результирующий файл version.properties будет выглядеть следующим образом:

PROJECT_VERSION=1.0.0-SNAPSHOT

Помимо всего вышесказанного, Release Candidate также позволяет устанавливать версию вашего проекта ( что вы, вероятно, сделаете на своем сервере CI) на основе версии API, определенной в вашем POM.

Если вы хотите увидеть пример кандидата-кандидата, который используется как часть жизненного цикла Maven, посмотрите на pom.xml моего другого проекта с открытым исходным кодом - Build Monitor для Jenkins.

Ответ 15

Удобное для понимания решение "все-в-одном", которое выводит версию проекта maven и подавляет посторонние выходы сообщений [INFO] и Download:

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

То же самое, но разделить на две строки:

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

Выходы: 4.3-SNAPSHOT

Итак, используя project.version в простой 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"

Другие решения на этой странице, похоже, не сочетали в себе все трюки.

Ответ 17

Я нашел правильный баланс для меня. После mvn package плагин target/maven-archiver/pom.properties создает target/maven-archiver/pom.properties с таким содержимым

version=0.0.1-SNAPSHOT
groupId=somegroup
artifactId=someArtifact

и я использую Bash только для его выполнения

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

затем

echo $version
0.0.1-SNAPSHOT

Конечно, запуск этого файла вовсе не безопасен, но его можно легко преобразовать в сценарий perl или bash для чтения и установки переменной окружения из этого файла.

Ответ 18

Это работало для меня в автономном режиме и не зависело от mvn:

VERSION=$(grep --max-count=1 '<version>' <your_path>/pom.xml | awk -F '>' '{ print $2 }' | awk -F '<' '{ print $1 }')
echo $VERSION

Ответ 19

Плагин Exec работает без какого-либо анализа вывода, поскольку вывод можно перенаправить в файл и вставить обратно в среду задания через плагин EnvInject:

введите описание изображения здесь

Ответ 20

Либо у вас mvn дается ответ (как подсказывает большинство ответов), либо вы извлекаете ответ из pom.xml. Единственным недостатком второго подхода является то, что вы можете очень легко извлечь значение тега <version/>, но оно будет иметь смысл только в том случае, если оно буквально, то есть не является свойством Maven. Я выбрал этот подход, потому что:

  • mvn - это способ подробного описания, и я просто не люблю фильтровать его вывод.
  • Запуск mvn очень медленный по сравнению с чтением pom.xml.
  • Я всегда использую литеральные значения в <version/>.

mvn-version - это оболочка zsh script, которая использует xmlstarlet для чтения pom.xml и распечатывает версию проекта (если он существует) или версии родительского проекта (если он существует):

$ mvn-version .
1.0.0-SNAPSHOT

Преимущество заключается в том, что он быстрее, чем запуск 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

Разница на моей машине больше двух порядков.

Ответ 21

Существует также один вариант без необходимости Maven:

grep -oPm1 "(?<=<version>)[^<]+" "pom.xml"

Ответ 22

Мне нужно именно это требование во время моей работы в Travis, но с несколькими значениями. Я начинаю с этого решения, но при многократном вызове это происходит очень медленно (мне нужно 5 выражений).

Я написал простой плагин maven для извлечения значений pom.xml в файл .sh.

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

Будет производить это:

#!/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';

теперь вы можете просто получить файл

source .target/ci-tools-env.sh

Веселись.

Ответ 23

Это, безусловно, самое простое решение для Bash Cut и Paste:

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

это отголоски

1.4

Ответ 24

Я использую однострочную оболочку в моей оболочке Unix...

кот pom.xml | grep "" | голова -n 1 | sed -e "s/version//g" | sed -e "s/\ s * [<>/] *//g"

Вы можете скрыть эту строку в сценарии оболочки или как псевдоним.

Ответ 25

это редактирование сверху

кот pom.xml | grep "" | голова -n 1 | sed -e "s/version//g" | sed -e "s/\ s * [<>/] *//g"

Я проверил это на cmdline работает хорошо

grep "" pom.xml | голова -n 1 | sed -e "s/version//g" | sed -e "s/\ s * [<>/] *//g"

это еще одна версия того же. У меня есть необходимость получить номер версии в Jenkins CI в k8s без установленного mvn, так что это очень полезно

Спасибо всем.

Ответ 26

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'

Я просто добавляю небольшое улучшение фильтра sed, которое я недавно использовал для извлечения project.version из вывода maven.

Ответ 27

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

Это то, что я использовал для получения номера версии, подумал, что было бы лучше сделать maven для этого

Ответ 28

Нижняя колонка Maven довольно стандартная:

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.609s
[INFO] Finished at: Wed May 21 18:02:38 MSK 2014
[INFO] Final Memory: 17M/736M
[INFO] ------------------------------------------------------------------------

Итак, вы можете использовать следующий код:

> version=$(mvn help:evaluate -Dexpression=project.version | tail -8 | head -1)
> echo $version