it-roy-ru.com

Как работает Maven для автоматических версий проекта при непрерывной доставке?

У меня есть веб-приложение, где мы внедряем в производство, когда функция готова, иногда это может быть пару раз в день, иногда это может быть пара недель между выпусками. 

В настоящее время мы не увеличиваем наши номера версий для нашего проекта, и все уже более года находятся в версии 0.0.1-SNAPSHOT ... Мне интересно, как Maven может осуществлять непрерывную доставку для веб-приложений. Кажется излишним увеличивать номер версии при каждом коммите, и никогда не менять номер версии, как мы делаем сейчас, также кажется неправильным.

Какова рекомендуемая лучшая практика для этого типа использования Maven?

Проблема на самом деле двойная:

  • Предварительный номер версии проекта в отдельном файле pom.xml (их может быть много).
  • Обновление номера версии во всех зависимых компонентах для использования последних версий друг друга.
44
ams

Я рекомендую следующую презентацию, в которой обсуждаются практические реалии непрерывной доставки с Maven:

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

38
Mark O'Connor

Это мое резюме, основанное на видео, на которое ссылается ответ Марка О'Коннора.

  • Решение требует DVCS, как Git и CI-сервер, как Jenkins. 
  • Не используйте сборки моментальных снимков в конвейере Continuous Delivery и не используйте плагин Maven Release.
  • Версии моментальных снимков, такие как 1.0-SNAPSHOT, преобразуются в реальные версии, такие как 1.0.buildNumber, где buildNumber - это номер задания Jenkins. 

Шаги алгоритма:

  1. Дженкинс клонирует репозиторий git с исходным кодом и говорит, что исходный код имеет версию 1.0-SNAPSHOT
  2. Jenkins создает ветку git с именем 1.0.JENKINS-JOB-NUMBER, поэтому версия снимка превращается в реальную версию 1.0.124
  3. Jenkins вызывает плагин maven version для изменения номера версии в файлах pom.xml с 1.0-SNAPSHOT на 1.0.JENKINS-JOB-NUMBER 
  4. Дженкинс вызывает mvn install
  5. Если mvn install будет успешным, то Jenkins передаст ветвь 1.0.JENKINS-JOB-NUMBER, и будет создана настоящая версия без снимка с подходящим тегом в git для последующего воспроизведения. Если mvn install завершится неудачей, Jenkins просто удалит только что созданную ветку и завершит сборку.

Я очень рекомендую видео, связанное с ответом Марка.

34
ams

Начиная с Maven 3.2.1, версии с поддержкой непрерывной доставки поддерживаются сразу после установки: https://issues.Apache.org/jira/browse/MNG-5576 Вы можете использовать 3 предопределенные переменные в версии:

${changelist}
${revision}
${sha1}

Итак, что вы в основном делаете: 

  1. Установите свою версию, например, 1.0.0-${revision}. (Вы можете использовать mvn versions:set, чтобы сделать это быстро и правильно в многомодульном проекте.)
  2. Поместите свойство <revision>SNAPSHOT</revision> для локальной разработки.
  3. В вашей среде CI запустите mvn clean install -Drevision=${BUILD_NUMBER} или что-то вроде этого или даже mvn clean verify -Drevision=${BUILD_NUMBER}.

Вы можете использовать, например, https://wiki.jenkins-ci.org/display/JENKINS/Version+Number+Plugin для создания интересных номеров сборок.

Как только вы обнаружите, что сборка стабильна (например, пройдет приемочные тесты), вы можете отправить версию в Nexus или другой репозиторий. Любые нестабильные сборки просто уходят в мусор.

14
Piotr Gwiazda

Есть несколько замечательных обсуждений и предложений, как обращаться с номером версии maven и непрерывной доставкой (CD) (я добавлю их после моей части ответа).

Итак, сначала мое мнение о версиях SNAPSHOT. В maven SNAPSHOT показывает, что он в настоящее время разрабатывается для конкретной версии до суффикса SNAPSHOT. Из-за этого такие инструменты, как Nexus или maven-release-plugin, имеют специальную обработку для SNAPSHOTS. Для Nexus они хранятся в отдельном репозитории, что позволяет обновлять несколько артефактов с помощью одной и той же версии выпуска SNAPSHOT. Таким образом, SNAPSHOT может измениться без вашего ведома об этом (потому что вы никогда не увеличиваете число в вашем pom). По этой причине я не рекомендую использовать зависимости SNAPSHOT в проекте, особенно в мире компакт-дисков, поскольку сборка больше не является надежной. 

SNAPSHOT как версия проекта будет проблемой, когда ваш проект используется другими, по вышеуказанным причинам.

Еще одна проблема SNAPSHOT для меня заключается в том, что она больше не отслеживается и не воспроизводится. Когда я вижу версию 0.0.1-SNAPSHOT в производстве, мне нужно выполнить поиск, чтобы выяснить, когда она была собрана, из какой ревизии она была собрана. Когда я нахожу выпуски этого программного обеспечения в файловой системе, мне нужно взглянуть на файл pom.properties или MANIFEST, чтобы увидеть, является ли это старым мусором или, возможно, самой последней и самой лучшей версией.

Чтобы избежать ручного изменения номера версии (особенно при сборке нескольких сборок в день), позвольте серверу сборки изменить номер для вас. Так что для развития я бы пошел с 

<major>.<minor>-SNAPSHOT

версия, но при создании новой версии Build Server может заменить SNAPSHOT на что-то более уникальное и отслеживаемое.

Например, одно из этого:

<major>.<minor>-b<buildNumber>
<major>.<minor>-r<scmNumber>

Таким образом, старший и второстепенный номер можно использовать для решения маркетинговых задач или просто для того, чтобы показать, что достигнут новый важный этап, и его можно изменить вручную, когда вы этого захотите. И buildNumber (номер с вашего сервера непрерывной интеграции) или scmNumber (ревизия Subversion или GIT) делают каждый выпуск уникальным и отслеживаемым. При использовании ревизии buildNumber или Subversion версии проекта даже сортируются (не с номерами GIT). С помощью buildNumber или scmNumber также довольно легко увидеть, какие изменения внесены в этот выпуск.

Другой пример - управление версиями stackoverflow, которое использует

<year>.<month>.<day>.<buildNumber>

И здесь недостающие ссылки:

9
mszalbach

НЕ ДЕЛАЙ ЭТОГО!

<Major>.<minor>-<build>

будет кусать вас сзади, потому что Maven рассматривает что-либо после дефиса как LEXICAL. Это означает, что версия 1 будет лексически выше 10.

Это плохо, так как если вы запрашиваете последнюю версию чего-то в Maven, то вышеупомянутый пункт выигрывает.

Решение состоит в том, чтобы использовать десятичную точку вместо дефиса, предшествующего номеру сборки.

СДЕЛАЙ ЭТО!

<Major>.<minor>.<build>

Верно иметь версии SNAPSHOT локально, но в качестве части сборки лучше использовать

mvn versions:set -DnewVersion=${major}.${minor}.${build.number}

Существуют способы получения основной/вспомогательной версии из pom, например, с помощью help: define и передают переменную среды перед вызовом версии: set. Это грязно, но я действительно почесал свою голову (и других в моей команде), чтобы сделать это проще, и (в то время) Мэйвен не был достаточно зрелым, чтобы справиться с этим. Я полагаю, что в Maven 2.3.1 может быть что-то, что может помочь в этом, поэтому эта информация может быть неактуальной.

Это нормально для группы разработчиков выпустить одну и ту же версию major.minor, но всегда полезно помнить, что незначительные изменения не нарушают целостности, а основные изменения имеют некоторые критические изменения API или устаревание функциональности/поведения.

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

6
user924272

В качестве отправной точки вы можете взглянуть на Maven: The Complete Reference. Версии проекта.

Тогда есть хороший пост о стратегии управления версиями.

2
dmitri

В моей работе над веб-приложениями мы сейчас используем этот шаблон управления версиями: 

<jenkins build num>-<git-short-hash> 

Пример: 247-262e37b9. 

Это хорошо, потому что он дает вам версию, которая всегда уникальна и прослеживается до версии jenkins build и git, которая его создала.

В Maven 3.2.1+ они, наконец, убили предупреждения об использовании $ {property} в качестве версии, чтобы их было действительно легко построить. Просто измените все ваши poms, чтобы использовать <version>${revision}</version> и построить с -Drevision=whatever. Единственная проблема с этим заключается в том, что в ваших выпущенных poms версия останется на ${revision} в реальном файле pom, что может вызвать всевозможные странные проблемы. Чтобы решить эту проблему, я написал простой плагин maven ( https://github.com/jeffskj/cd-versions-maven-plugin ), который выполняет замену переменных в файле.

1
Jeff S