Статьи

Зависимости Maven Build

Пользователи Maven и Gradle, которые знакомы с зависимостями выпуска и моментального снимка, могут не знать о зависимостях моментального снимка TeamCity или предположить, что они каким-то образом связаны с Maven (что не соответствует действительности). Пользователи TeamCity, которые знакомы с зависимостями артефактов и моментальных снимков, могут не знать, что добавление подключаемого модуля Artifactory позволяет им также использовать зависимости артефактов и строить зависимости, помимо предоставляемых TeamCity.

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

В этом первом посте рассматриваются снимки и зависимости Maven . Во втором посте рассматриваются зависимости артефактов и снимков, предоставляемые TeamCity , а в третьей и заключительной части рассматриваются зависимости артефактов и сборок, предоставляемые плагином TeamCity Artifactory .

Внутренние и внешние зависимости

Процессы сборки могут выполняться в полной изоляции, проверяя всю базу кода и создавая приложение с нуля. Это относится к проектам, где соответствующие двоичные зависимости (если они есть) хранятся в VCS вместе с источниками проекта. Однако во многих других случаях сценарии сборки полагаются на внутренние или внешние зависимости какого-либо рода.

Внутренние зависимости удовлетворяются нашим собственным кодом, где мы имеем полный контроль над проектом, который может быть разделен на несколько модулей или подпроектов. Внешние зависимости удовлетворяются чужим кодом (над которым у нас нет контроля), и мы используем его или используем в качестве клиентов. Это может быть сторонняя библиотека, такая как Spring, или компонент, разработанный другой группой.

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

Другой аспект характеристик внутренней и внешней зависимости выражается в том, как их версии указываются в скрипте сборки. Внутренние зависимости обычно определяются с использованием версий моментальных снимков, в то время как внешние зависимости используют версии выпуска. Определение версий «моментальный снимок» и «выпуск» было придумано Maven, который первым предложил идею управления зависимостями с помощью инструмента сборки. Если вы знакомы с автоматическим управлением зависимостями, не стесняйтесь пропустить следующий раздел, в котором представлен краткий обзор его работы.

Автоматическое управление зависимостями

В Maven зависимости задаются декларативно в скрипте сборки, позже подход, за которым следуют более новые инструменты сборки, такие как Gradle , Buildr и sbt .

Maven:

1
2
3
4
5
6
<dependency>
    <groupId>org.codehaus.groovy</groupId>
    <artifactId>groovy-all</artifactId>
    <version>1.8.6</version>
    <scope>compile</scope>
</dependency>

Gradle:

1
compile "org.codehaus.groovy:groovy-all:1.8.6"

Buildr:

1
compile.with "org.apache.axis2:axis2:jar:1.6.1"

SBT:

1
libraryDependencies += "org.twitter4j"  % "twitter4j-core"  % "2.2.5"

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

Например, "compile org.codehaus.groovy:groovy-all:1.8.6" будет обозначать Groovy "org.codehaus.groovy:groovy-all" для версии "1.8.6" , используемой для компиляции исходного кода и вызова теста , Переключение области действия на «тест» или «время выполнения» затем сузит видимость библиотеки до «только тесты» или «только время выполнения», соответственно.

Когда начинается сборка, зависимости располагаются либо в локальном репозитории артефактов, управляемом инструментом сборки (аналогично кешу браузера), либо загружаются из удаленных общедоступных или закрытых репозиториев, таких как Maven Central , Artifactory или Nexus . Затем инструмент сборки добавляет разрешенные артефакты в соответствующие пути классов в соответствии с их областями действия. При сборке артефактов сборки, таких как архивы "*.war" или "*.ear" , все необходимые зависимости также корректно обрабатываются и упаковываются.

Хотя управление зависимостями, по-видимому, является неотъемлемой частью практически любой сборки, не все инструменты сборки предоставляют встроенную поддержку для него: Ant и MSBuild не имеют этой возможности, что в некоторой степени позже было устранено Ivy и NuGet . Тем не менее, принятие Ivy было медленнее, чем Maven, в то время как NuGet — инструмент только для .NET. Со временем репозитории артефактов Maven и Maven Central стали де-факто механизмом для распространения и совместного использования артефактов Java. Возможность разрешать и развертывать их с помощью репозиториев Maven стала необходимостью для всех новых инструментов сборки Java.

Зависимости релиза и снимка

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

Зависимости выпуска — это те, которые имеют фиксированный номер версии, например, версия "1.8.6" дистрибутива Groovy. Какой бы репозиторий артефактов не использовался сборкой, и всякий раз, когда он пытается найти эту зависимость, всегда ожидается, что он разрешит один и тот же артефакт. Это основной принцип зависимости релиза: «Та же версия = тот же артефакт» . В связи с этим инструменты сборки не проверяют наличие обновлений зависимостей выпуска после его обнаружения и повторно загружают артефакт только после очистки локального кэша. И все это, конечно, имеет смысл, поскольку мы никогда не ожидаем найти расходящиеся артефакты одной и той же библиотеки с одинаковым номером версии!

Зависимости моментальных снимков различны, и, как следствие, с ними сложнее справиться. Версии зависимостей моментальных снимков заканчиваются специальным "-SNAPSHOT" словом "-SNAPSHOT" , например "3.2.0-SNAPSHOT" . Это ключевое слово сигнализирует инструментам сборки о периодической проверке артефакта в удаленном хранилище на наличие обновлений; по умолчанию Maven выполняет эту проверку ежедневно . Таким образом, функция зависимостей моментальных снимков заключается в том, чтобы зависеть от чужой незавершенной работы (например, «ночные сборки»): когда разработка продукта переходит от версии "X" к версии "X+1" его модули имеют версию "X+1" "X+1-SNAPSHOT" .

Зависимости снимка Неопределенность

Если основным принципом зависимостей выпуска было «Одна и та же версия = один и тот же артефакт» (после выпуска версии «Х» библиотеки, ее артефакты одинаковы во всем мире, навсегда), принцип « моментальных снимков» равен «Та же версия = постоянно обновляющаяся Артефакт » . Преимущество этого подхода в том, что он позволяет получать частые обновления без необходимости выпускать ежедневные выпуски, что было бы крайне непрактично. Недостатком этого является, однако, неопределенность — использование зависимостей моментальных снимков в сценарии сборки усложняет определение того, какая версия использовалась при конкретном выполнении сборки. Мой "maven-about-plugin" хранит текстовый файл «about» в каждом артефакте моментального снимка, чтобы лучше определить его происхождение, такое как версия VCS и номер сборки; это может быть полезно, но это решает только половину проблемы.

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

Один из возможных подходов в этой ситуации — заблокировать версию зависимости в скрипте сборки, используя метку времени, чтобы она стала "3.2.0-20120119.134529-1" а не "3.2.0-SNAPSHOT" . Это эффективно делает зависимости моментальных снимков идентичными зависимостям выпуска и отключает механизм автоматического обновления, делая невозможным использование актуальной версии, даже если она доступна, если не обновлена ​​временная метка.

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

Резюме

В этой статье представлен обзор автоматического управления зависимостями с помощью инструментов сборки Java, а также введение в зависимости релиза и моментального снимка Maven. Также объясняется, как преимущества снэпшотов становятся спорными в контексте воспроизводимости сборки и конвейеров сборки.

В следующих статьях блога будут рассмотрены цепочки сборки TeamCity и изоляция сборки Artifactory, которые позволяют использовать согласованные, воспроизводимые и актуальные версии моментальных снимков во всей цепочке сборок без блокировки их временных меток в сценарии сборки. Еще не все!

Ссылка: Зависимости Maven Build от нашего партнера JCG Евгения Голдина в блоге Goldin ++ .