Релизим проект на Java с Maven на новый лад

habr.png

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

Идеи, которые привнес maven в мир разработки, были крайне востребованы и быстро завоевали популярность: определение стандартного воркфлоу проекта, стандартная модель директорий, и много еще чего, что уже давно воспринимается, как должное.

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

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

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

Далее мы попробуем изменить мир к лучшему и упростить себе жизнь.

Дисклеймер

Я предполагаю, что читатель знаком с Java, Maven, жизненным циклом разработки и настройкой CI/CD, понимает зачем все это ему надо и вообще ниндзя.

В современных реалиях выпускать несколько версий в неделю и даже в день считается если не нормой, то целью. И, в таких условиях, хранение версии в файле проекта приводит к очень большим накладным расходам.

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

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

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

Возможно, все эти проблемы кому то и покажутся надуманными, но при более менее большом количестве проектов, управление и настройка CI/CD превращается в крайне неприятный и запутанный процесс.

Теперь, когда проблема видна, давайте попробуем ее решить, так чтоб не сильно менять набор инструментов, процессов, и вообще чтоб оно само, как-нибудь.

Что требуется:

  • версия хранится единожды, в виде тега репозитория
  • возможна пересборка любого релиза, набор шагов должен быть таким-же, как и в случае нового релиза
  • не нужны права на запись в репозиторий
  • мы все так же используем maven в качестве менеджера проекта


Предположим, что CI/CD сделает для нас получение тега и чекаут проекта.

Допустим, что тег для нас заполнен CI/CD в переменную окружения RELEASE_TAG, тогда, для того чтоб выпустить релиз, мы должны выполнить следующие команды:

mvn -B versions:set -DnewVersion=$RELEASE_TAG (1)
mvn -B deploy (2)


1 — обновляет версии в pom-файлах проекта и его модулей
2 — выполняет сборку и, при правильной настройке проекта, загружает артефакты в репозиторий

Не забываем ставить флаг -B, иначе лог исполнения превращается в тыкву.

Важно: для того чтоб не возникло путаницы и однозначно было видно как и откуда идет сборка, надо установить версию проекта в что-нибудь абстрактное, например DEVELOPMENT-SNAPSHOT. Воспользоваться можно той же самой командой: version: set. Операция разовая, мы ведь больше не храним версию проекта в файле.

В результате изменений можно удалить конфигурацию maven-release-plugin и scm блока из pom файла.

» Из минусов:
Если у вас где либо используются SNAPSHOT версии, то может начаться путаница, теперь все SNAPSHOT версии выглядят одинаково. И, возможно, такой способ релизить проекты не для вас.

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

» Из плюсов:

  • Все требования удовлетворены, и даже больше!
  • версия хранится только в теге проекта
  • сборка новой и пересборка старой версии выполняется таким-же набором команд что и оригинальная версия
  • отпала необходимость прав на коммит в проект
  • набор инструментов остался тот-же
  • бонус: конфигурация проекта упростилась


Вот так, две строчки опять спасли мир.
На этом и все, спасибо за внимание!

© Habrahabr.ru