Сборка проектов в конвейере: Maven, Gradle, npm

Рейтинг: 48.7% · 7 голосов
Подробный курс по Jenkins и CI/CD: установка и настройка, плагины и Configuration as Code, конвейеры (pipeline) и Jenkinsfile, declarative и scripted, агенты, Docker и Kubernetes, общие библиотеки на Groovy, безопасность и credentials, интеграции (SonarQube, артефакты), траблшутинг. Актуально на 2026.
Ответить
Аватара пользователя
Andrey_CICD
Сообщения: 47
Зарегистрирован: 11 май 2026, 05:31

Сборка проектов в конвейере: Maven, Gradle, npm

Сообщение Andrey_CICD »

Оглавление курса (47)
  1. Что такое Jenkins и зачем нужен CI/CD
  2. Jenkins в 2026: версии, экосистема и сравнение с GitLab CI и GitHub Actions
  3. Архитектура Jenkins: контроллер, агенты, узлы и исполнители
  4. Установка Jenkins: пакеты, Docker и Kubernetes
  5. Первичная настройка Jenkins: мастер, плагины, пользователи
  6. Плагины Jenkins: установка, обновление и ключевой набор
  7. Configuration as Code (JCasC): настройка Jenkins декларативно
  8. Конвейеры Jenkins и Jenkinsfile: pipeline as code
  9. Scripted против Declarative: два синтаксиса конвейера
  10. Структура конвейера: node, stage, steps и первый pipeline
  11. Генератор сниппетов, запуск конвейера и Replay
  12. Типы заданий Jenkins: Freestyle, Pipeline, Multibranch и Organization
  13. Декларативный конвейер: структура pipeline, agent, stages
  14. agent, environment и переменные в конвейере
  15. tools, options, parameters и triggers в декларативном конвейере
  16. stages, parallel и matrix: организация этапов
  17. Условное выполнение when и блок post
  18. Триггеры сборки: webhook от GitHub, SCM polling и расписание
  19. Параметры сборки и пользовательский ввод
  20. Управление потоком: timeout, retry, sleep и waitUntil
  21. Параллелизм и блокировки: parallel, lock, milestone
  22. Постобработка и уведомления о результате сборки
  23. Groovy для Jenkins: основы скриптового конвейера
  24. Скриптовый конвейер: логика, циклы и функции
  25. Общие библиотеки Jenkins: Shared Libraries
  26. Подключение и загрузка общих библиотек
  27. Шаги оболочки: sh, bat, powershell и коды возврата
  28. Переменные среды, withEnv и рабочие пространства
  29. Работа с файлами, артефактами и отпечатками
  30. Сборка проектов в конвейере: Maven, Gradle, npm (вы здесь)
  31. Качество кода: SonarQube и покрытие тестами
  32. Управление артефактами: публикация в Nexus и Artifactory
  33. Docker в Jenkins: образы как агенты сборки
  34. Сборка и публикация Docker-образов из конвейера
  35. Jenkins в Kubernetes: динамические pod-агенты
  36. Развёртывание в Kubernetes из конвейера
  37. Безопасность Jenkins: аутентификация и матрица прав
  38. Учётные данные Jenkins: credentials в конвейере
  39. Безопасность сценариев: Groovy sandbox и Vault
  40. Уведомления и отчёты: email, Slack, Telegram, HTML
  41. Blue Ocean и интерфейс Jenkins в 2026
  42. Автоматизация Jenkins: CLI, REST API и script console
  43. Поиск и устранение неисправностей: читаем логи конвейера
  44. Типичные ошибки конвейера: сериализация и неутверждённый код
  45. Эксплуатация Jenkins: бэкап, обновление, масштабирование
  46. Конвертация и миграция: от Freestyle к Jenkinsfile
  47. Итог: сквозной CI/CD конвейер и Jenkins против альтернатив в 2026
Зачем нам отдельный урок про сборку

До этого мы крутили учебные пайплайны, которые печатали "hello" и вызывали echo. На реальном проекте конвейер начинается с того, что нужно собрать приложение из исходников - и тут вылезает первая боль. На машине разработчика "у меня всё собирается", а на сервере jenkins сборка падает: не та версия JDK, нет Maven в PATH, npm тянет другие зависимости, тесты внезапно красные. Классика "works on my machine".

Цель этого урока - сделать так, чтобы jenkins build был воспроизводимым: одинаковым на ноуте разработчика, на агенте и в проде. Разберём, как подключить инструменты сборки, как выглядит честный стейдж компиляции и тестов для Java и Node, как кешировать зависимости и публиковать отчёты по тестам. И почему в 2026 году самый надёжный способ - собирать внутри контейнера, а не на "толстом" агенте с предустановленным софтом.

Маленькая сверка по версиям, чтобы не строить на песке. Актуальная LTS на середину 2026 - Jenkins 2.541.x (вышла 21 января 2026). Линия 2.541.x - последняя, где ещё поддерживается Java 11; начиная с апрельского baseline контроллер требует минимум Java 17, а weekly-сборки уже просят Java 21. Это касается JVM, на которой работает сам Jenkins. JDK, которым ты собираешь приложение, - отдельная история и задаётся в пайплайне.

Изображение

Откуда берутся JDK, Maven, Gradle и Node: два подхода

Есть ровно два рабочих способа дать стейджу нужные инструменты.

Подход 1: директива tools. В "Manage Jenkins -> Tools" ты заводишь установки - JDK, Maven, Gradle, NodeJS (последнее требует плагина NodeJS). Каждой даёшь имя, например jdk21 или maven3. Дальше в Jenkinsfile блок tools подставляет их в PATH и выставляет JAVA_HEME автоматически. Если установка помечена как "Install automatically", Jenkins сам скачает нужную версию при первом запуске.

Код: Выделить всё

pipeline {
    agent any
    tools {
        jdk 'jdk21'
        maven 'maven3'
    }
    stages {
        stage('Build') {
            steps {
                sh 'java -version'
                sh 'mvn -B -ntp package'
            }
        }
    }
}
Просто, но есть минус: ты зависишь от того, что админ настроил инструменты в UI с теми же именами. Это глобальное состояние контроллера, и оно живёт отдельно от кода проекта. Имя tools в Jenkinsfile обязано совпадать с именем в Global Tool Configuration, иначе пайплайн упадёт ещё до первого шага.

Подход 2: Docker-агент. Тут окружение описано прямо в репозитории: ты говоришь "собирай вот в этом образе", и Jenkins поднимает контейнер, монтирует туда workspace и выполняет шаги внутри. Версия JDK и Maven зашита в образ - значит, она одинаковая у всех и не зависит от настроек сервера. Это и есть воспроизводимость.

Код: Выделить всё

pipeline {
    agent {
        docker {
            image 'maven:3.9-eclipse-temurin-21'
            args '-v $HOME/.m2:/root/.m2'
        }
    }
    stages {
        stage('Package') {
            steps {
                sh 'mvn -B -ntp clean package'
            }
        }
    }
}
Аргумент args монтирует локальный кеш Maven (.m2) внутрь контейнера, чтобы не качать полинтернета на каждый запуск. По умолчанию для 2026 года я советую именно Docker-агент или эфемерные pod-агенты в Kubernetes - к ним вернёмся ниже. Подход с tools оставляй для простых случаев и legacy-инсталляций.

Типовой CI-стейдж: jenkins maven, gradle и npm

Любая jenkins сборка приложения раскладывается на одни и те же фазы: checkout -> зависимости -> компиляция -> тесты -> упаковка. Меняется только инструмент. Разберём по очереди.

Jenkins Maven. Команда mvn package сама прогоняет жизненный цикл: компиляцию, тесты (surefire), сборку jar. Флаг -B (batch mode) убирает интерактив, -ntp (no transfer progress) гасит шумный лог скачивания.

Код: Выделить всё

pipeline {
    agent { docker { image 'maven:3.9-eclipse-temurin-21'; args '-v $HOME/.m2:/root/.m2' } }
    options { timeout(time: 20, unit: 'MINUTES') }
    stages {
        stage('Checkout') { steps { checkout scm } }
        stage('Build')    { steps { sh 'mvn -B -ntp -DskipTests clean package' } }
        stage('Test')     { steps { sh 'mvn -B -ntp test' } }
    }
    post {
        always {
            junit 'target/surefire-reports/*.xml'
            archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
        }
    }
}
Обрати внимание: тесты вынесены в отдельный стейдж и публикуются в блоке post с условием always. Так отчёт по тестам появится даже если сборка упала. Шаг junit парсит XML-отчёты surefire - для Maven это target/surefire-reports/*.xml.

Jenkins Gradle. Здесь ключевое правило - запускать обёртку ./gradlew, а не глобальный gradle. Обёртка фиксирует версию Gradle прямо в репозитории, и сборка не зависит от того, что стоит на агенте.

Код: Выделить всё

stage('Build') {
    steps {
        sh 'chmod +x gradlew'
        sh './gradlew --no-daemon clean build'
    }
}
Команда ./gradlew build уже включает тесты. Флаг --no-daemon важен в CI: демон Gradle полезен для локальной разработки, но на эфемерном агенте он только мешает - живёт дольше сборки и жрёт память. Отчёты тестов Gradle кладёт в build/test-results, поэтому в post пишем junit 'build/test-results/**/*.xml', а артефакт - build/libs/*.jar.

Jenkins npm. Для фронтенда и Node-сервисов в CI всегда используй npm ci, а не npm install. Команда ci ставит зависимости строго по package-lock.json, без "плавающих" версий, и она заметно быстрее. Перед запуском чистит node_modules - это ровно та детерминированность, которая нужна на сервере.

Код: Выделить всё

pipeline {
    agent { docker { image 'node:22-alpine' } }
    stages {
        stage('Install') { steps { sh 'npm ci' } }
        stage('Build')   { steps { sh 'npm run build' } }
        stage('Test')    { steps { sh 'npm test -- --ci' } }
    }
    post {
        always { junit 'reports/junit/*.xml' }
    }
}
Чтобы получить XML для шага junit, настрой в проекте репортер - например jest-junit для Jest. Сам по себе npm test пишет в консоль, Jenkins же хочет машинный отчёт.

Кеширование зависимостей и сборка в Kubernetes

Скачивать зависимости заново на каждый build - дорого и медленно. Стратегия зависит от типа агента.

На постоянном агенте всё просто: каталоги ~/.m2, ~/.gradle и node_modules переживают перезапуски, и кеш греется сам собой. На эфемерном агенте (контейнер живёт только время сборки) каталог исчезает вместе с контейнером, поэтому кеш надо вынести наружу. В Docker-агенте это volume на хост (мы это сделали через args '-v $HOME/.m2:/root/.m2'). В Kubernetes - persistentVolumeClaim, смонтированный в pod, либо внешний прокси-репозиторий вроде Nexus или Artifactory, который кеширует артефакты централизованно.

Эфемерные pod-агенты в Kubernetes - это золотой стандарт масштабирования jenkins build в 2026. Каждая сборка получает свежий pod, который удаляется после завершения. Никакого мусора между сборками, никакого "загрязнённого" workspace, и контроллер не держит простаивающих агентов. Описывается это через kubernetes-плагин прямо в Jenkinsfile - pod-шаблоном с нужными контейнерами:

Код: Выделить всё

pipeline {
    agent {
        kubernetes {
            yaml '''
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: maven
    image: maven:3.9-eclipse-temurin-21
    command: ['sleep']
    args: ['infinity']
'''
        }
    }
    stages {
        stage('Build') {
            steps {
                container('maven') {
                    sh 'mvn -B -ntp clean package'
                }
            }
        }
    }
}
Шаг container('maven') переключает выполнение в нужный контейнер пода. Можно описать сразу несколько контейнеров - например maven для сборки и kaniko для упаковки образа - и гонять шаги в разных. Сам подключаемый pod-шаблон удобно держать в Configuration as Code (JCasC), чтобы дефолтные настройки облака не задавались мышкой в UI.

Типичные грабли
  • Запуск глобального gradle/mvn вместо ./gradlew или версии из tools. Сборка зелёная у тебя и красная у коллеги - потому что версии разные. Лечится обёрткой или Docker-агентом.
  • npm install в CI вместо npm ci. Подтягивает свежие минорные версии зависимостей, и сборка перестаёт быть детерминированной. На сервере - только npm ci.
  • junit в обычном steps вместо post { always { ... } }. Если упадёт компиляция, до публикации отчёта дело не дойдёт, и ты не увидишь, какие тесты красные. Всегда always.
  • Gradle daemon на эфемерном агенте. Висит после сборки, ест память, иногда ловит чужой кеш. Добавляй --no-daemon.
  • Путаница, какой JDK где. Java для самого Jenkins (минимум 17 на LTS 2026) и JDK для сборки приложения - это разные вещи. Версию сборки задавай образом контейнера или директивой tools, не надеясь на системную.
  • Не примонтирован кеш на Docker-агенте. Каждый запуск качает зависимости с нуля, сборка тянется минутами. Прокинь volume на .m2 или .gradle.
Для сравнения: в GitLab CI и GitHub Actions кеш и образ задаются декларативно прямо в yaml (keyword cache, директива image, actions/cache). В Jenkins это делается явно руками - чуть больше церемоний, зато полный контроль над тем, где и как живёт кеш. Это плата за гибкость зрелого инструмента.

Мини-лаба

Повтори руками, минут на 20-30.
  • Возьми любой простой Maven-проект (хоть сгенерированный архетипом) и напиши Jenkinsfile с Docker-агентом maven:3.9-eclipse-temurin-21.
  • Разнеси сборку на стейджи Checkout, Build, Test. В post { always } добавь junit и archiveArtifacts с jar.
  • Запусти, посмотри вкладку "Test Result". Сломай один тест нарочно - убедись, что сборка стала UNSTABLE (жёлтой), а не FAILED, и отчёт всё равно опубликовался.
  • Примонтируй кеш .m2 через args, запусти дважды и сравни время второго прогона.
  • Бонус: повтори то же для Gradle (./gradlew build, --no-daemon) или для Node (npm ci && npm run build).
Контрольные вопросы
  • Чем npm ci отличается от npm install и почему в CI нужен именно ci?
  • Почему шаг junit ставят в post { always }, а не в обычный steps?
  • Какие два способа дать стейджу нужный JDK/Maven ты знаешь и в чём плюс Docker-агента для воспроизводимости?
  • Где живёт кеш зависимостей на эфемерном pod-агенте в Kubernetes и почему его нельзя оставить внутри контейнера?
Итог

Реальная jenkins сборка - это всегда одна и та же цепочка: checkout, зависимости, компиляция, тесты, упаковка. Maven делает это через mvn package, Gradle через ./gradlew build, Node через npm ci и npm run build. Инструменты подключаются либо директивой tools, либо - что надёжнее в 2026 - Docker-агентом или эфемерным pod-агентом в Kubernetes, где версии зашиты в образ. Кеш выноси наружу, отчёты тестов публикуй в post { always } через junit, а артефакты сохраняй archiveArtifacts. Сделаешь так - и "у меня собирается" перестанет быть отговоркой.
👍4 ❤️3 🔥1 😄 🤔3
Аватара пользователя
sanfranx
Сообщения: 1
Зарегистрирован: 22 май 2026, 06:33

Re: Сборка проектов в конвейере: Maven, Gradle, npm

Сообщение sanfranx »

Споткнулся ровно на грабле с junit - засунул его в steps, компиляция упала и отчёта нет. Перенёс в post always, теперь видно красные тесты даже на сломанной сборке. Спасибо за разбор.
👍 ❤️ 🔥 😄 🤔3
Аватара пользователя
klentz
Сообщения: 1
Зарегистрирован: 13 май 2026, 17:41

Re: Сборка проектов в конвейере: Maven, Gradle, npm

Сообщение klentz »

Вопрос про кеш в k8s: PVC на каждый под не дороговато выходит при параллельных сборках? Думаю поставить Nexus как прокси-репо, или это оверкилл для небольшой команды?
👍3 ❤️1 🔥 😄 🤔
Ответить
← Предыдущая глава
Работа с файлами, артефактами и отпечатками
Следующая глава →
Качество кода: SonarQube и покрытие тестами

Все главы курса «Jenkins: конвейеры CI/CD от основ до продакшена»

Поделиться темой: ✈ Telegram VK
Похожие запросы: как установить jenkins на linux и в dockergroovy в jenkins scripted pipeline как написатьпараметры и параллельные стейджи в jenkins pipelinejenkins error как читать и чинить ошибки сборкиjenkins сборка и деплой в прод как настроитьструктура declarative pipeline в jenkins: stages, agent, steps

Вернуться в «Jenkins: конвейеры CI/CD от основ до продакшена»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 2 гостя