Именно эту боль решает главная фича второго поколения Jenkins. Конвейер описывается кодом и лежит рядом с приложением. Этот подход называется pipeline as code, а файл с описанием - Jenkinsfile. Давай разберёмся, как это работает и почему это сердце всего курса.
Что такое Jenkinsfile и почему pipeline as code меняет правила
Jenkins pipeline - это вся последовательность сборки, тестов, упаковки и деплоя, описанная как единый процесс. Раньше эта логика жила внутри Jenkins, в его базе конфигураций. Теперь она переезжает в обычный текстовый файл с именем Jenkinsfile, который ты кладёшь в корень своего репозитория - туда же, где лежит исходный код.
Что такое Jenkinsfile по сути? Это groovy-скрипт особого вида, описывающий шаги твоего конвейера. Но не пугайся слова "скрипт": в 2026 году стандарт - declarative pipeline, декларативный синтаксис, где ты описываешь не "как программировать", а "что должно произойти". Выглядит почти как конфиг.
Почему jenkins конвейер в виде кода радикально лучше кликанья мышкой во Freestyle:
- Версионируется. Jenkinsfile лежит в git. Каждое изменение процесса сборки - это коммит с автором, датой и diff. Откатить плохое изменение так же просто, как откатить баг в коде.
- Ревьюится. Поменял этап деплоя - открыл pull request. Коллега видит ровно те строки, которые ты изменил, и может оставить комментарий до того, как это уедет в прод.
- Живёт вместе с веткой. В feature-ветке можно держать свою версию конвейера. Слил ветку - конвейер обновился атомарно вместе с кодом, который он собирает.
- Переживает рестарт. Здесь работает механизм durability: Jenkins сериализует состояние пайплайна на диск по ходу выполнения. Если контроллер перезапустится посреди долгой сборки, конвейер сможет продолжиться, а не начнётся с нуля. У Freestyle такого нет в принципе.

Где живёт Jenkinsfile и как Jenkins его подхватывает
Канонический путь - корень репозитория, файл ровно с именем Jenkinsfile, без расширения. Дальше ты создаёшь в Jenkins джобу типа Pipeline и указываешь, что определение брать "from SCM" - то есть из системы контроля версий. Jenkins при запуске сам клонирует репозиторий, читает Jenkinsfile и выполняет то, что в нём описано.
Ещё мощнее - Multibranch Pipeline. Ты указываешь Jenkins на репозиторий целиком, и он сам сканирует все ветки. В каждой ветке, где есть Jenkinsfile, автоматически создаётся отдельный конвейер. Появилась новая ветка с Jenkinsfile - появился новый пайплайн. Удалили ветку - джоба убралась. Открыли pull request - Jenkins может собрать и его. Ничего руками заводить не нужно.
Первый минимальный pipeline: anatomy из stages и steps
Хватит теории, посмотрим на живой Jenkinsfile. Вот минимальный рабочий declarative pipeline:
Код: Выделить всё
pipeline {
agent any
stages {
stage('Build') {
steps {
echo 'Собираем проект'
sh 'make build'
}
}
}
}
- pipeline - корневой блок. С него начинается любой declarative-конвейер. Всё описание живёт внутри его фигурных скобок.
- agent - где выполнять. agent any означает "на любом доступном агенте". Можно прибить к конкретному лейблу: agent { label 'linux' }, или запускать каждый этап в своём docker-контейнере.
- stages - контейнер для этапов. Внутри лежат отдельные stage.
- stage - один логический этап с человекочитаемым именем: Build, Test, Deploy. Именно эти прямоугольники ты потом видишь в визуализации Stage View.
- steps - конкретные шаги внутри этапа. sh выполняет shell-команду, echo печатает в лог. Шаг - это атомарное действие.
Код: Выделить всё
pipeline {
agent any
environment {
APP_VERSION = '1.4.0'
}
options {
timeout(time: 30, unit: 'MINUTES')
disableConcurrentBuilds()
}
stages {
stage('Build') {
steps {
sh 'mvn -B clean package'
}
}
stage('Test') {
steps {
sh 'mvn test'
}
post {
always {
junit 'target/surefire-reports/*.xml'
}
}
}
stage('Deploy') {
when {
branch 'main'
}
steps {
sh "./deploy.sh ${APP_VERSION}"
}
}
}
post {
failure {
echo 'Сборка упала, шлём уведомление в чат'
}
always {
cleanWs()
}
}
}
Declarative - стандарт по умолчанию, потому что он проверяется на синтаксис до запуска и читается линейно. Но иногда нужна динамика: сгенерировать список этапов в цикле, хитрая логика ветвления. Тогда внутри declarative можно открыть блок script { } со scripted-кодом на groovy, либо писать весь конвейер в scripted-стиле. Правило простое: declarative по умолчанию, scripted - точечно, где упираешься в ограничения.
Кстати, про визуализацию. В книгах 2018-2019 годов активно рекламировали Blue Ocean - красивый UI для пайплайнов. В 2026 он де-факто заброшен и в режиме поддержки. Воспринимай его как наследие, не строй на нём процессы. Современная визуализация - встроенный Stage View и Pipeline Graph View, а сам конвейер всегда определяется через Jenkinsfile, а не через клики.
Типичные грабли
- Забыл agent. Без директивы agent declarative-конвейер не пройдёт валидацию. agent обязателен либо на уровне pipeline, либо в каждом stage.
- Путаешь declarative и scripted. Если файл начинается с node { } - это scripted. Если с pipeline { } - declarative. Смешивать синтаксис двух стилей напрямую нельзя, scripted-вставки идут только внутри script { }.
- Многострочный shell. Используй sh '''...''' с тройными кавычками для нескольких команд. И помни: каждый sh-шаг по умолчанию падает на первой же ненулевой команде, потому что Jenkins запускает его с set -e.
- Секреты прямо в коде. Никогда не вписывай пароли и токены в Jenkinsfile - он же в git. Бери их через credentials(): environment { TOKEN = credentials('my-token') }.
- Имена этапов как у мусора. stage('stage1') ничего не говорит. Зови этапы по делу: Build, Unit Tests, Deploy Staging - это твоя документация в Stage View.
Закрепляем. Что повторить самостоятельно:
- Установи Jenkins LTS (актуальная линейка - 2.541.x от января 2026 на Java 17, новые сборки 2.555.x уже требуют Java 21). Подними хоть в docker одной командой.
- Создай git-репозиторий, положи в корень файл Jenkinsfile из первого примера выше.
- В Jenkins заведи джобу типа Pipeline, в Definition выбери "Pipeline script from SCM", укажи свой репозиторий.
- Запусти сборку и открой Stage View - убедись, что видишь прямоугольник этапа Build.
- Добавь второй stage с именем Test и шагом sh 'echo running tests'. Закоммить, запусти снова, посмотри, как появился новый этап.
- Сломай синтаксис специально (убери закрывающую скобку) и убедись, что declarative ловит ошибку до запуска сборки.
- Чем pipeline as code принципиально лучше Freestyle-джобы, настроенной через UI? Назови минимум три преимущества.
- Из каких обязательных блоков состоит минимальный declarative pipeline и за что отвечает каждый?
- В чём разница между stages, stage и steps?
- Что такое durability и как механизм помогает конвейеру пережить рестарт контроллера?
Jenkinsfile - это твой конвейер, превращённый в код и положенный в репозиторий рядом с приложением. Pipeline as code даёт версионирование, ревью, durability и одинаковый процесс для всех веток. Базовая анатомия проста: pipeline -> stages -> stage -> steps, и её хватает, чтобы собрать первый рабочий конвейер уже сегодня. Declarative - твой выбор по умолчанию на 2026 год, scripted держи в запасе для динамики. Дальше мы будем наращивать на этот скелет параметры, параллельные этапы, агентов в Kubernetes и Configuration as Code - но фундамент именно здесь.