Как получить версию проекта 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
Я провел некоторые исследования и обнаружил следующее:
-
Maven обвиняют в том, что он не может быть легко интегрирован в сценарии работы системы, поскольку он не следует некоторым рекомендациям относительно инструментов CLI. (ссылка: https://youtu.be/1ILEw6Qca3U?t=372)
-
Вдохновленный предыдущим утверждением, я решил взглянуть на исходный код maven, а также на плагин maven-help-plugin. Кажется, что они немного исправили переключатель maven -q (я использую версию 3.5.3), так что теперь, если вы пропустите его, вы не получите все раздражающие средства регистрации, не связанные со смыслом, которые не позволяют maven быть используется в автоматизированных сценариях. Таким образом, вы должны быть в состоянии использовать что-то вроде этого:
mvn help:evaluate -Dexpression=project.version -q
Проблема в том, что эта команда ничего не печатает, потому что по умолчанию плагин справки выводится через регистратор, который был отключен переключателем -q. (последняя доступная версия плагина - 3.1.0, выпущенная 3 июня 2018 г.)
-
Карл Хайнц Марбез (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"
Другие решения на этой странице, похоже, не сочетали в себе все трюки.
Ответ 16
Должна быть проще, поскольку эта ошибка исправлена в maven-help-plugin 3.0.0: MPH-99 Evaluate не имеет выхода в тихом режиме.
Ответ 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