Жизненный цикл сборки Maven: фазы, цели плагинов и команды - Вопросы
Всего: 6 вопросов
1. Что такое жизненный цикл сборки Maven и какие жизненные циклы встроены в Maven?
Что такое жизненный цикл сборки Maven и какие жизненные циклы встроены в Maven?
Жизненный цикл сборки (build lifecycle) - заранее определённая упорядоченная последовательность фаз, через которые проходит проект: проверка, компиляция, тесты, упаковка, установка и публикация. Реальную работу на фазах делают привязанные к ним цели (goals) плагинов.
В Maven три независимых встроенных цикла:
- default - 23 фазы от
validateдоdeploy: компиляция, тесты, упаковка, установка в локальный репозиторий, публикация (mvn package,mvn verify,mvn install). - clean - фазы
pre-clean,clean,post-clean; удаляет каталогtargetцельюclean:clean. - site - фазы
pre-site,site,post-site,site-deploy; генерирует HTML-сайт проекта с отчётами вtarget/site(maven-site-plugin, отчёты задаёт раздел<reporting>).
Фаза одного цикла не запускает фазы другого: mvn install не очищает target, а mvn clean ничего не компилирует. Слово clean обозначает и цикл, и его главную фазу, поэтому в старых статьях clean и site ошибочно называют «фазами, стоящими особняком».
Фазы разных циклов можно перечислить в одной команде, и Maven выполнит их слева направо: mvn clean package site - сначала цикл clean до фазы clean, затем default до package, затем site до site.
2. Какие фазы есть в жизненном цикле default и что выполняется при запуске mvn package?
Какие фазы есть в жизненном цикле default и что выполняется при запуске mvn package?
В цикле default 23 фазы, но в командах обычно используют семь основных:
validate- проверка корректности POM;compile- компиляция основного кода вtarget/classes(ресурсы копируются перед ней);test- компиляция и запуск unit-тестов (maven-surefire-plugin), упавший тест останавливает сборку;package- упаковка в формат из<packaging>(jar, war);verify- проверки качества и результатов интеграционных тестов;install- копирование артефакта и POM в локальный репозиторий~/.m2/repository;deploy- публикация в удалённый репозиторий из<distributionManagement>.
Остальные фазы (initialize, generate-sources, process-resources, test-compile, prepare-package, pre-integration-test, integration-test, post-integration-test и др.) - точки, куда плагины встраивают подготовительные шаги; напрямую их почти не вызывают.
Главное правило: mvn <фаза> выполняет все фазы того же цикла от первой до указанной включительно. Поэтому mvn package сам скопирует ресурсы, скомпилирует код и тесты, прогонит тесты и создаст jar, а verify, install и deploy не запустятся. Если тест падает, сборка останавливается на test, и jar не создаётся. Фаза, к которой не привязано ни одной цели, ничего не делает и в логе не видна.
В Maven 4 фазы и команды те же, но вместо pre-* и post-* появились хуки before: и after: для любой фазы (старые имена сохранены).
3. Чем фаза отличается от цели (goal) плагина в Maven?
Чем фаза отличается от цели (goal) плагина в Maven?
Фаза - шаг жизненного цикла (package), сама по себе она ничего не делает: работу выполняют привязанные к ней цели. Цель - конкретное действие плагина (compiler:compile, jar:jar).
- При запуске фазы Maven выполняет все предыдущие фазы того же цикла и привязанные к ним цели.
- При запуске цели выполняется только она одна, без предыдущих шагов.
Синтаксис цели: короткая форма префикс:цель (mvn jar:jar) или полные координаты mvn org.apache.maven.plugins:maven-jar-plugin:3.4.1:jar. Цели вызывают напрямую для разовых действий вне сборки: mvn dependency:tree, mvn help:effective-pom. Фазы и цели можно смешивать: mvn clean compile dependency:tree выполнит цикл clean, затем default до compile и потом цель.
Типичные ошибки: mvn clean jar:jar даёт BUILD SUCCESS, но пустой jar (JAR will be empty) - компиляции не было; mvn surefire:test после правки кода прогоняет тесты по старым .class-файлам. В логе цель, вызванная из командной строки, помечена id выполнения default-cli, а цель из стандартной привязки - default-... (например, default-jar). Для сборки запускайте фазы: mvn clean package, mvn test.
4. Как цели плагинов привязываются к фазам жизненного цикла Maven и как посмотреть привязки своего проекта?
Как цели плагинов привязываются к фазам жизненного цикла Maven и как посмотреть привязки своего проекта?
Стандартные привязки задаёт элемент <packaging>: для каждого типа упаковки в Maven встроен свой набор (lifecycle mapping). Поэтому jar-проект собирается без единого объявленного плагина.
Привязки для packaging = jar (Maven 3.9.x):
process-resources-resources:resources;compile-compiler:compile;process-test-resources-resources:testResources;test-compile-compiler:testCompile;test-surefire:test;package-jar:jar;install-install:install;deploy-deploy:deploy.
У war на фазе package вместо jar:jar выполняется war:war, у pom остаются только install и deploy - компиляции и тестов нет. Свои цели можно привязать к любой фазе в <build><plugins>; если к фазе привязано несколько целей, сначала выполняются стандартные, затем объявленные в pom.xml в порядке объявления. Добавить свою фазу обычно не нужно: цель привязывают к существующей (генератор кода - к generate-sources, проверку стиля - к verify).
Фактические привязки проекта с учётом родителя и версий плагинов показывает mvn help:describe -Dcmd=compile: напротив каждой фазы указана цель или Not defined, если к фазе ничего не привязано.
5. Чем maven-surefire-plugin отличается от maven-failsafe-plugin и почему интеграционные тесты запускают командой mvn verify?
Чем maven-surefire-plugin отличается от maven-failsafe-plugin и почему интеграционные тесты запускают командой mvn verify?
- Surefire запускает unit-тесты на фазе
test, подключён по умолчанию. Классы по умолчанию:Test*,*Test,*Tests,*TestCase. Упавший тест сразу останавливает сборку. Отчёты -target/surefire-reports. - Failsafe запускает интеграционные тесты, его нужно явно объявить в
<build><plugins>с целямиintegration-testиverify(элементphaseне нужен: фазы по умолчанию совпадают с именами целей). Классы:IT*,*IT,*ITCase. Отчёты -target/failsafe-reports.
Интеграционные тесты идут после package: им нужен собранный артефакт и окружение (база, контейнер, сервер). Запуск окружения привязывают к pre-integration-test, остановку - к post-integration-test. Если IT падает, failsafe не роняет сборку сразу: она доходит до post-integration-test (окружение останавливается) и падает на verify.
Поэтому запускать нужно mvn verify (или install, deploy). Сама фаза integration-test тестов не запускает - это делает привязанная к ней цель failsafe. mvn integration-test останавливается на одноимённой фазе: окружение остаётся запущенным, а failsafe:verify не выполняется, и можно получить BUILD SUCCESS с красными тестами. Класс *IT без failsafe не запускается вообще.
Пропуск: -DskipITs - только интеграционные, -DskipTests - все тесты.
6. Какие команды сборки Maven нужны в повседневной работе и чем mvn clean verify отличается от mvn clean install?
Какие команды сборки Maven нужны в повседневной работе и чем mvn clean verify отличается от mvn clean install?
mvn clean verify- очистка, компиляция, все тесты и проверки; артефакт остаётся вtarget. Подходит для проверки перед коммитом и на CI.mvn clean install- то же плюс копирование артефакта в~/.m2/repository. Нужен, когда артефакт должен подхватить другой, отдельно собираемый проект. В многомодульном проекте модули получают результаты соседей внутри одной сборки (reactor), устанавливать их для этого не нужно.mvn package -DskipTests- тесты компилируются, но не запускаются (в логеTests are skipped.).-Dmaven.test.skip=trueне компилирует тесты вовсе: ошибка в тестовом коде останется незамеченной, а test-jar не будет создан, и зависимый от него модуль упадёт. Поэтому предпочтительнее -DskipTests.-pl shop-core -am- модуль и модули, от которых он зависит;-amd- модуль и зависящие от него;-rf :shop-web- продолжить упавшую сборку с модуля.-o- офлайн-режим;-U- принудительная проверка обновлений SNAPSHOT-зависимостей.mvn test -Dtest=OrderServiceTest#create- один тестовый класс или метод; для интеграционных -mvn verify -Dit.test=OrderRepositoryIT.
clean перед каждой сборкой не обязателен: он нужен после удаления или переименования классов, смены версии Java или плагинов и на CI.