Как собирается Java проект в пайплайне
Что проверяют
Понимаете ли вы, что происходит внутри mvn или gradle, а не только знаете команду. DevOps-инженеру важны воспроизводимость, скорость и то, что в прод уходит ровно тот артефакт, который прошёл тесты. Следом спрашивают, как ускорить сборку и где хранить артефакты.
Как отвечать
Опишите пайплайн по этапам:
- окружение: сборка в контейнере с зафиксированной JDK, например образ
eclipse-temurinнужной LTS (21 или 25), и через обёртки./mvnwили./gradlew, чтобы версия инструмента была записана в репозитории, а не зависела от раннера; - зависимости: кэш
~/.m2/repositoryили~/.gradle/cachesс ключом по хэшуpom.xmlлибо файлов сборки. Без кэша каждый прогон заново качает сотни мегабайт; - сборка и тесты: в Maven фазы идут по жизненному циклу
compile,test,package,verify,install,deploy, и вызов поздней фазы выполняет все предыдущие. В CI обычно хватает./mvnw -B verify: юнит-тесты гонит Surefire, интеграционные (*IT) Failsafe. В Gradle аналог./gradlew build, он включаетcheckи тесты; - качество: отчёты JUnit XML в интерфейс CI, покрытие JaCoCo, анализ SonarQube, проверка уязвимостей зависимостей;
- артефакт: JAR с версией из тега или SHA коммита уходит в Nexus или Artifactory через
deploy, а для контейнерной поставки собирается образ: multi-stage Dockerfile с JDK на этапе сборки и JRE в финальном слое, либо Jib илиspring-boot:build-imageбез ручного Dockerfile. Образ тегируется тем же SHA и пушится в registry.
Главный принцип: собрать один раз и продвигать один и тот же артефакт по окружениям, меняя только конфигурацию.
Где спотыкаются
Пишут mvn clean install, а следующим шагом mvn test. Тесты прогоняются дважды, а install в CI только кладёт артефакт в локальный .m2 раннера, который потом выбрасывается.
Пересобирают приложение отдельно для каждого окружения. Тогда на прод едет не то, что тестировали, и воспроизвести баг по версии уже нельзя.
Добавляют -DskipTests «чтобы быстрее» вместо кэша и параллельного запуска тестов. Скорость покупается пропущенными регрессиями.