«1. Обзор

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

В этом руководстве мы узнаем, как использовать плагин Versions Maven для поддержания наших зависимостей в актуальном состоянии.

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

2. Синтаксис диапазона версий Maven

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

Этот синтаксис все еще действителен, используется в нескольких проектах и, следовательно, его стоит знать:

Maven Version Range Syntax

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

2.1. Устаревший синтаксис

Maven2 также предоставил два специальных значения метаверсии для достижения результата: LATEST и RELEASE.

LATEST ищет самую новую возможную версию, в то время как RELEASE стремится к последней версии, отличной от SNAPSHOT.

Они действительно по-прежнему абсолютно применимы для разрешения обычных зависимостей.

Однако этот устаревший метод обновления приводил к непредсказуемости там, где CI требовалась воспроизводимость. Следовательно, они устарели для разрешения зависимостей плагинов.

3. Подключаемый модуль Versions Maven

Подключаемый модуль Versions Maven является фактически стандартным способом управления версиями в настоящее время.

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

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

3.1. Тестовый пример

Прежде чем начать, давайте определим наш тестовый пример:

    три ВЫПУСКА с жестко закодированной версией один ВЫПУСК с версией свойства и один СНИМОЧНЫЙ ШОТ
<dependencies>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.3</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-collections4</artifactId>
        <version>4.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-compress</artifactId>
        <version>${commons-compress-version}</version>
    </dependency>
    <dependency>
        <groupId>commons-beanutils</groupId>
        <artifactId>commons-beanutils</artifactId>
        <version>1.9.1-SNAPSHOT</version>
    </dependency>
</dependencies>

<properties>        
    <commons-compress-version>1.15</commons-compress-version>
</properties>

Наконец, давайте также исключим артефакт из процесс при определении плагина:

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>versions-maven-plugin</artifactId>
            <version>2.7</version>
            <configuration>
                <excludes>
                    <exclude>org.apache.commons:commons-collections4</exclude>
                </excludes>
            </configuration>
        </plugin>
    </plugins>
</build>

4. Отображение доступных обновлений

Прежде всего, чтобы просто узнать, можем ли мы обновить наш проект и как, правильный инструмент для работы — это версии: display-dependency- обновления:

mvn versions:display-dependency-updates

mvn versions:display-dependency-updates

Как мы видим, процесс включал каждую версию RELEASE. В него были включены даже commons-collections4, так как исключение в конфигурации относится к процессу обновления, а не к открытию.

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

5. Обновление зависимостей

При первом запуске обновления подключаемый модуль создает резервную копию файла pom.xml с именем pom.xml.versionsBackup.

Хотя каждая итерация будет изменять pom.xml, файл резервной копии сохранит исходное состояние проекта до момента, когда пользователь зафиксирует (через mvn version:commit) или отменит (через mvn version:revert) весь процесс.

5.1. Преобразование SNAPSHOT в RELEASE

Иногда бывает так, что проект включает SNAPSHOT (версия, которая все еще находится в стадии интенсивной разработки).

Мы можем использовать version:use-releases, чтобы проверить, был ли опубликован соответствующий РЕЛИЗ, и даже больше, чтобы одновременно преобразовать наш SNAPSHOT в этот РЕЛИЗ:

mvn versions:use-releases

mvn versions:use-releases

5.2. Обновление до следующего ВЫПУСКА

Мы можем портировать каждую зависимость, не относящуюся к SNAPSHOT, до ее ближайшей версии с версиями: use-next-releases:

mvn versions:use-next-releases

mvn versions:use-next-releases

Мы ясно видим, что плагин обновил commons-io, commons-lang3 , и даже commons-beanutils, который больше не является SNAPSHOT, до их следующей версии.

«Что наиболее важно, он игнорировал commons-collections4, который исключен из конфигурации плагина, и commons-compress, номер версии которого задается динамически через свойство.

5.3. Обновление до последней версии

Обновление каждой зависимости, отличной от SNAPSHOT, до ее последней версии работает таким же образом, просто изменяя цель на версии: use-latest-releases:

mvn versions:use-latest-releases

mvn versions:use-latest-releases

6. Фильтрация нежелательных версий ~ ~~ Если мы хотим игнорировать определенные версии, конфигурация плагина может быть настроена на динамическую загрузку правил из внешнего файла:

Наиболее примечательно, что \u003crulesUri\u003e также может ссылаться на локальный файл:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>versions-maven-plugin</artifactId>
    <version>2.7</version>
    <configuration>
        <rulesUri>http://www.mycompany.com/maven-version-rules.xml</rulesUri>
    </configuration>
</plugin>

~ ~~ 6.1. Глобальное игнорирование версий

<rulesUri>file:///home/andrea/maven-version-rules.xml</rulesUri>

Мы можем настроить наш файл правил так, чтобы он игнорировал версии, соответствующие определенному регулярному выражению:

6.2. Игнорирование версий для каждого правила

<ruleset comparisonMethod="maven"
  xmlns="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0 
  http://mojo.codehaus.org/versions-maven-plugin/xsd/rule-2.0.0.xsd">
    <ignoreVersions>
        <ignoreVersion type="regex">.*-beta</ignoreVersion>
    </ignoreVersions>
</ruleset>

Наконец, если наши потребности более специфичны, мы можем вместо этого создать набор правил:

7. Заключение

<ruleset comparisonMethod="maven"
  xmlns="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0 
    http://mojo.codehaus.org/versions-maven-plugin/xsd/rule-2.0.0.xsd">
    <rules>
        <rule groupId="com.mycompany.maven" comparisonMethod="maven">
            <ignoreVersions>
                <ignoreVersion type="regex">.*-RELEASE</ignoreVersion>
                <ignoreVersion>2.1.0</ignoreVersion>
            </ignoreVersions>
        </rule>
    </rules>
</ruleset>

Мы увидели, как проверять и обновлять зависимости проекта безопасным, автоматическим и совместимым с Maven3 способом.

Как всегда, исходный код доступен на GitHub вместе со сценарием, который поможет продемонстрировать все шаг за шагом и без сложностей.

Чтобы увидеть его в действии, просто скачайте проект и запустите в терминале (или в Git Bash, если используете Windows):

«

./run-the-demo.sh