Получение версии артефакта maven из ветки git
У нас есть требование к потоку данных, которое по существу означает, что нам нужно иметь версию артефакта модуля, внешне определяемую из текущей ветки в git.
т.е. если мы находимся на главной ветки в git, мне нужно <version>master-...</version>
, и если мы находимся в ветке bugfixX, мне нужен <version>bugfixX-....</version>
для сгенерированного артефакта для этого pom.xml.
Ранее я обнаружил, что https://github.com/koraktor/mavanagaiata может предоставить хэш SHA-1 как свойство, и из документации видно, что он также может предоставить ветку, поэтому возможно, если бы это можно было запустить достаточно рано, мы могли бы установить свойство и просто положить <version>${our.version}</version>
в pom. Если это возможно, я бы очень хотел увидеть рабочий pom.xml(и вознаградить за него 500 очков).
Если нет, я предполагаю, что мы либо выполняем предварительную обработку, либо "git checkout" делаем дополнительную магию с некоторыми из перехватов (которые я еще не пробовал, рабочий код тоже был бы хорош).
У нас есть pom верхнего уровня, который можно запустить для создания файла свойств в ".." перед созданием модулей, где эта функциональность я прошу о необходимости.
Любые предложения о том, как это решить?
Ответы
Ответ 1
Действительно, Maven не может изменить версию своего собственного проекта за один проход с другими целями. Кроме того, насколько я знаю, Maven не поддерживает произвольные свойства в теге <version>
. Поэтому для выполнения цели требуется отдельное выполнение, которое изменит версию POM. Существуют различные плагины, которые могут это сделать - для этого случая можно использовать цель versions:set
из плагина versions
- http://mojo.codehaus.org/versions-maven-plugin/set-mojo.html
Итак, можно выполнить его, например, следующим образом:
mvn versions:set -DgenerateBackupPoms=false -DnewVersion=$branch-SNAPSHOT
где переменная $branch
должна содержать текущее имя ветки Git; его можно извлечь с помощью git rev-parse
, например:
branch=$(git rev-parse --abbrev-ref HEAD)
Но все-таки нужно его каким-то образом выполнить. Вы можете делать это вручную, но это громоздко. Итак, я думаю, что самым надежным решением было бы приблизиться к этому со стороны Git. То есть - крюк Git. Вот полный крюк Git post-checkout
, который выполнит задание (тот же код, что и выше, с некоторой фильтрацией для запуска крюка только тогда, когда ветвь проверена, а не только отдельные файлы):
#!/bin/bash
echo 'Will change the version in pom.xml files...'
# check if the checkout was to checkout a branch
if [ $3 != '1' ]
then echo 'git checkout did not checkout a branch - quitting';exit
fi
# get current branch name
branch=$(git rev-parse --abbrev-ref HEAD)
version=$branch-SNAPSHOT
# run maven versions plugin to set new version
mvn versions:set -DgenerateBackupPoms=false -DnewVersion=$version
echo 'Changed version in pom.xml files to $version'
Поместите это содержимое в файл PROJECTDIR\.git\hooks\post-checkout
. Обратите внимание, что файл hook должен быть исполняемым для его запуска (chmod +x post-checkout
).
Несколько заметок о плагине versions
- он довольно гибкий и поддерживает множество параметров и имеет несколько других целей, которые могут быть полезны, в зависимости от структуры вашего проекта (используете ли вы родительские помпы или нет, у детей есть свои версии или они происходят от родителя и т.д.). Таким образом, вышеперечисленный крючок может быть немного изменен, чтобы поддержать конкретный случай, используя другие цели из плагина versions
или указав дополнительные параметры.
Плюсы:
- Robust
- Не нужно ничего менять в файлах pom.xml, чтобы сделать эту работу.
- Эта "функциональность" может быть отключена просто путем деактивации крюка (удалить или сделать не исполняемым) - снова, никаких изменений не требуется в pom.xml
Минусы:
- Нельзя заставить других использовать крючок - он должен быть установлен вручную после клонирования репо (или вы можете предоставить script для установки крюка, если предполагается, что Git пользователи боятся касаться материала внутри .git).
UPDATE
В дальнейшем это более сложная версия hook, которая не только установит версию в название ветки, но также сохранит суффикс старой версии. Например, при старой версии master-1.0-SNAPSHOT
переход на ветку feature1
изменит версию проекта на feature1-1.0-SNAPSHOT
. Этот bash script страдает от нескольких проблем (требуется имя ветки без символа тире (-
) в имени и принимает только версию корневого помпы), но может дать представление о том, как можно увеличить крючок: учитывая сочетание команд mvn и bash, вы можете извлекать и обновлять довольно много информации в POM.
#!/bin/bash
echo 'Will change the version in pom.xml files...'
# check if the checkout was to checkout a branch
if [ $3 != '1' ]
then echo 'git checkout did not checkout a branch - quitting';exit
fi
# get current branch name
branch=$(git rev-parse --abbrev-ref HEAD)
# get current version of the top level pom
current_version=$(mvn help:evaluate -Dexpression=project.version | grep -v '\[.*')
# extract version suffix
suffix=$(echo $current_version | cut -d \- -f 2)
# build new version
version=$branch-$suffix
# run maven versions plugin to set new version
mvn versions:set -DgenerateBackupPoms=false -DnewVersion=$version
echo 'Changed version in pom.xml files to $version'
Ответ 2
Извините, что возродил этот вопрос и опубликовал в последнее время другое решение, но можно действительно изменить версию maven динамически и использовать некоторые функции git, немного похожие на git describe
.
Проект, который делает это jgitver-maven-plugin (отказ от ответственности, я автор), он использует jgitver библиотека на основе jgit, чтобы получить версию проекта maven из git.
![введите описание изображения здесь]()
Он очень прост в использовании в качестве расширения maven
...
<build>
<extensions>
<extension>
<groupId>fr.brouillard.oss</groupId>
<artifactId>jgitver-maven-plugin</artifactId>
<version>0.1.0</version>
</extension>
</extensions>
...
</build>
...
Расширение также можно использовать в качестве расширения плагина, а затем позволяет больше конфигурации, например, если вы не хотите использовать SNAPSHOTS.
См. Страницу для описания сценариев полного использования.
Существует также gradle плагин, который делает более или менее то же самое.
[править 1]: ответ на комментарий Торбьорна Равна Андерсена
Плагин не изменяет исходные файлы pom или файлы build.gradle.
Для плагина maven модификации выполняются как в памяти в Maven Object Model, так и записываются во временный файл в каталоге temp. Расчет основан только на метаданных git (теги, коммиты,...).
Эта не модификация позволяет не загрязнять историю git. Если вы удовлетворены фиксацией git, отметьте тегами git tag -a x.y.z
и mvn deploy
: все.
Версия в ваших файлах проекта теперь бесполезна и может быть установлена, например, на 0.
На сегодняшний день, и благодаря IDEA-155733, только последние версии EAP IntelliJ работают с плагином maven.
Eclipse и Netbeans не имеют проблем.
Ответ 3
Отказ от ответственности: я автор
Мое расширение ядра Maven будет фактически устанавливать версию на основе текущей ветки или тега. Вы можете настроить шаблоны формата пользовательских версий, как вам нравится.
https://github.com/qoomon/maven-branch-versioning-extension
Пример формата версии ![enter image description here]()
Ответ 4
Если достаточно указать тег и версию git в имени файла артефакта, вы можете использовать maven-jgit-buildnumber-plugin:
<build>
<finalName>${artifactId}-${git.buildnumber}</finalName>
<plugins>
<plugin>
<groupId>ru.concerteza.buildnumber</groupId>
<artifactId>maven-jgit-buildnumber-plugin</artifactId>
<version>1.2.7</version>
<executions>
<execution>
<id>git-buildnumber</id>
<goals>
<goal>extract-buildnumber</goal>
</goals>
<phase>prepare-package</phase>
</execution>
</executions>
</plugin>
<!-- more plugins -->
</plugins>
</build>
Ответ 5
Вы пробовали использовать этот плагин?: https://github.com/ktoso/maven-git-commit-id-plugin. Вы можете настроить его для создания файла свойств со всей необходимой информацией о состоянии вашего репо:
- филиал
- описывают
- commitId
- buildUserName
- buildUserEmail
- buildTime
- commitUserName
- commitUserEmail
- commitMessageShort
- commitMessageFull
- commitTime
Ответ 6
Вы проверили buildnumber-maven-plugin, который дает вам возможность использовать номер версии git. Но вам нужно было что-то другое. Кроме того, я бы предложил сделать что-то вроде:
1.0.0-SNAPSHOT
1.0.0-SNAPSHOT
beeing on master
на ветке вы можете просто изменить версию на
1.0.0-BF-SNAPSHOT
Ответ 7
Начиная с maven-3.5.0, в теге версии есть поддержка свойств $ {revision}, $ {sha1} и $ {changelist}. Эта функция может быть достаточной для ваших целей, если, например, вы хотите включить фирменное имя Git в версию для задания сборки CI. Посмотреть версии Maven CI Friendly
По сути, в вашем pom.xml замените фиксированную версию на:
<version>${revision}${changelist}</version>
Установите значения по умолчанию для ревизии и списка изменений в корневом .mvn/maven.config
проекта, создав файл .mvn/maven.config
содержащий:
-Drevision=1.2.3
-Dchangelist=-SNAPSHOT
Проверьте этот файл в управлении версиями, обновите его, когда вы поднимаете ревизию вашего проекта.
В вашей системе CI вы можете затем переопределить переменную списка изменений, используя очищенное представление имени ветки Git, например.
BRANCHNAME=$(git rev-parse --abbrev-ref HEAD | sed -E -e '[email protected][^0-9A-Za-z.-][email protected]@g')
mvn clean install -Dchangelist="-${BRANCHNAME}"
(Вы можете предпочесть git symbolic-ref --short HEAD
для извлечения ответвления, YMMV)
Ваш артефакт, созданный системой CI для feature/branchname
ветки feature/branchname
будет иметь суффикс версионной ветки, например:
yourproject-1.2.3-feature-branchname.jar
в то время как разработчики, которые не используют переопределения, все равно будут создавать его как:
yourproject-1.2.3-SNAPSHOT.jar