Перейти к основному содержимому

7.04. Справочник по Jenkins

Разработчику Архитектору Инженеру

Справочник по Jenkins

Общие сведения

Jenkins — это система непрерывной интеграции и непрерывной доставки (CI/CD), написанная на Java. Она автоматизирует сборку, тестирование и развертывание программного обеспечения. Jenkins работает как серверное приложение и предоставляет веб-интерфейс для управления задачами, конфигурациями и выполнением процессов.

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

Jenkins может работать в двух режимах:

  • Freestyle-проекты — классический способ определения заданий через графический интерфейс.
  • Pipeline-проекты — современный подход, основанный на декларативном или скриптовом описании процесса в виде кода (Pipeline as Code).

Архитектура Jenkins

Jenkins состоит из следующих ключевых компонентов:

Master-узел

Master-узел управляет планированием заданий, хранением конфигураций, веб-интерфейсом и взаимодействием с агентами. Он не обязан выполнять сами задания, особенно в распределенных средах.

Агенты (агентские узлы, worker nodes)

Агенты выполняют задания, назначенные master-узлом. Они могут быть:

  • локальными (на том же хосте, что и master),
  • удаленными (через SSH, JNLP или Docker),
  • динамическими (в облаке или в Kubernetes).

Агенты регистрируются в master-узле и получают метки, по которым Jenkins направляет к ним выполнение заданий.

Плагины

Плагины добавляют поддержку новых инструментов, протоколов, шагов и возможностей. Установка происходит через веб-интерфейс или файловую систему ($JENKINS_HOME/plugins).

Конфигурационные файлы

Основные файлы конфигурации находятся в директории $JENKINS_HOME:

  • config.xml — глобальная конфигурация Jenkins.
  • jobs/ — описание каждого задания.
  • nodes/ — описание агентов.
  • credentials.xml — учетные данные (если не используется плагин Credentials Binding).
  • plugins/ — установленные плагины.

Типы заданий (Job Types)

Jenkins поддерживает несколько типов заданий:

Freestyle Project

Классическое задание, настраиваемое через веб-интерфейс. Содержит этапы:

  • ограничения по месту запуска,
  • управление исходным кодом (SCM),
  • шаги сборки,
  • действия после сборки.

Pipeline

Задание, определяемое в виде скрипта Groovy. Поддерживает два синтаксиса:

  • Declarative Pipeline — строгая структура с предопределенными секциями.
  • Scripted Pipeline — гибкий сценарий на Groovy с полным контролем над логикой.

Multibranch Pipeline

Автоматически обнаруживает ветки в репозитории и создает отдельный pipeline для каждой ветки. Использует файл Jenkinsfile в корне каждой ветки.

Organization Folder

Группирует репозитории по организации (например, GitHub Organization). Автоматически сканирует все репозитории и применяет Multibranch Pipeline ко всем, содержащим Jenkinsfile.

External Job

Интегрирует внешние процессы, не управляемые Jenkins напрямую, но отправляющие результаты выполнения в Jenkins.

Matrix Project (через плагин)

Позволяет запускать одно задание с разными комбинациями параметров (например, ОС × версия JDK).


Pipeline: основы

Pipeline описывается в файле Jenkinsfile, который должен находиться в корне репозитория (при использовании Pipeline as Code).

Декларативный синтаксис

Структура декларативного pipeline:

pipeline {
agent any
environment { }
options { }
parameters { }
triggers { }
stages {
stage('Build') {
steps { }
}
}
post { }
}
Блок agent

Определяет, где будет выполняться pipeline или его этап.

Возможные значения:

  • any — любой доступный агент.
  • none — этапы должны указывать собственный агент.
  • label 'name' — агент с указанной меткой.
  • node { label '...' } — аналогично, но с дополнительными параметрами.
  • docker 'image' — запуск в контейнере Docker.
  • dockerfile [true] — сборка образа из Dockerfile в репозитории.
  • kubernetes — запуск в кластере Kubernetes (требуется плагин).

Пример:

agent { label 'linux && docker' }
Блок environment

Определяет переменные окружения для всего pipeline или конкретного этапа.

Пример:

environment {
DB_HOST = 'localhost'
BUILD_NUMBER = "${BUILD_NUMBER}"
}

Поддерживается маскирование чувствительных значений через credentials():

environment {
AWS_SECRET_KEY = credentials('aws-secret-key-id')
}
Блок options

Настраивает поведение pipeline.

Часто используемые опции:

  • buildDiscarder(logRotator(...)) — управление хранением сборок.
  • disableConcurrentBuilds() — запрет параллельных запусков.
  • timeout(time: 1, unit: 'HOURS') — таймаут выполнения.
  • retry(3) — повтор при падении.
  • skipDefaultCheckout() — пропуск автоматического клонирования репозитория.
  • timestamps() — добавление временных меток к логам.
  • ansiColor('xterm') — поддержка цветных логов (требуется плагин).

Пример:

options {
timeout(time: 30, unit: 'MINUTES')
buildDiscarder(logRotator(numToKeepStr: '10'))
}
Блок parameters

Определяет параметры, запрашиваемые при ручном запуске.

Типы параметров:

  • string(name: 'VERSION', defaultValue: '1.0', description: '')
  • booleanParam(name: 'DEPLOY', defaultValue: false)
  • choice(name: 'ENV', choices: ['dev', 'stage', 'prod'])
  • text(name: 'NOTES', defaultValue: '')
  • password(name: 'SECRET', defaultValue: '')
  • fileParam(name: 'UPLOAD_FILE') — загрузка файла (ограничено).

Пример:

parameters {
string(name: 'APP_NAME', defaultValue: 'myapp')
choice(name: 'TARGET_ENV', choices: ['test', 'prod'])
}
Блок triggers

Определяет автоматические триггеры запуска.

Поддерживаемые триггеры:

  • cron('H 2 * * *') — запуск по расписанию (аналог crontab).
  • pollSCM('H/5 * * * *') — опрос SCM на изменения.
  • upstream(upstreamProjects: 'other-job', threshold: hudson.model.Result.SUCCESS) — запуск после успешного завершения другого задания.
  • genericTrigger — универсальный webhook (требуется плагин Generic Webhook Trigger).

Пример:

triggers {
cron('H 3 * * 1') // каждый понедельник в 3 часа ночи
}
Блок stages

Содержит последовательность этапов (stage). Каждый этап может содержать:

  • steps
  • agent
  • environment
  • tools
  • when
  • post
  • parallel (внутри steps)

Пример:

stages {
stage('Test') {
steps {
sh 'npm test'
}
}
}
Блок post

Определяет действия после завершения pipeline. Выполняется всегда, независимо от результата, если не указано иное.

Условия:

  • always
  • success
  • failure
  • unstable
  • changed
  • aborted
  • notBuilt

Пример:

post {
failure {
emailext(
subject: "Pipeline failed: ${env.JOB_NAME}",
body: "Check: ${env.BUILD_URL}",
recipientProviders: [[$class: 'DevelopersRecipientProvider']]
)
}
}

Встроенные шаги (Steps)

В Jenkins Pipeline шаги — это атомарные действия, выполняемые в рамках этапа (stage). Они могут быть как встроенными, так и предоставленными плагинами. Ниже перечислены основные встроенные шаги, доступные без установки дополнительных плагинов.

Управление исходным кодом

  • checkout scm — клонирует репозиторий, указанный в настройках задания.
  • checkout([$class: 'GitSCM', ...]) — явная настройка Git через Groovy.
  • git url: '...', branch: '...' — упрощённый способ клонирования Git-репозитория.

Выполнение команд

  • sh 'command' — выполнение команды в оболочке Unix/Linux/macOS.
  • bat 'command' — выполнение команды в Windows CMD.
  • powershell 'command' — выполнение PowerShell-скрипта (требуется плагин).

Управление файлами и директориями

  • deleteDir() — удаляет всё содержимое текущей рабочей директории.
  • dir('path') { ... } — временно меняет рабочую директорию.
  • fileExists 'filename' — проверяет существование файла (возвращает true/false).
  • readFile 'file' — читает содержимое файла как строку.
  • writeFile file: 'name', text: 'content' — записывает текст в файл.
  • archiveArtifacts artifacts: 'pattern', fingerprint: true — сохраняет артефакты сборки.
  • unarchive mapping: ['pattern': 'dest'] — распаковывает ранее сохранённые артефакты.

Переменные и окружение

  • env.VAR = 'value' — присваивание переменной окружения.
  • withEnv(['VAR=value']) { ... } — временная установка переменных окружения.
  • echo 'message' — вывод сообщения в лог.
  • currentBuild.result = 'SUCCESS' — принудительная установка статуса сборки.

Учетные данные

  • withCredentials([string(credentialsId: 'id', variable: 'VAR')]) { ... } — безопасное использование секретов.
  • Поддерживаемые типы:
    • string — текстовый секрет.
    • usernamePassword — логин и пароль.
    • file — секрет в виде файла.
    • sshUserPrivateKey — SSH-ключ.
    • certificate — TLS-сертификат.

Пример:

withCredentials([usernamePassword(credentialsId: 'my-creds', usernameVariable: 'USER', passwordVariable: 'PASS')]) {
sh 'curl -u $USER:$PASS https://api.example.com'
}

Уведомления

  • emailext to: 'user@example.com', subject: '...', body: '...' — отправка email (требует плагин Email Extension).
  • mail to: '...', subject: '...', body: '...' — базовая отправка email.
  • slackSend channel: '#ci', message: 'Build failed' — отправка в Slack (требует плагин Slack Notification).

Работа с Docker

  • docker.build('image-name', '.') — сборка образа.
  • docker.image('name').run('--rm') — запуск контейнера.
  • docker.withRegistry('https://registry.example.com', 'creds-id') { ... } — работа с приватным registry.

Запуск других заданий

  • build job: 'other-job', parameters: [string(name: 'VERSION', value: '1.0')] — запуск другого pipeline.
  • waitUntil { ... } — ожидание выполнения условия (например, завершения внешнего процесса).

Контроль потока

  • retry(3) { ... } — повтор блока до 3 раз при ошибке.
  • timeout(time: 10, unit: 'MINUTES') { ... } — ограничение времени выполнения.
  • sleep time: 30, unit: 'SECONDS' — пауза.
  • input message: 'Continue?' — ожидание ручного подтверждения.

Работа с JSON, XML, YAML

  • readJSON file: 'config.json' — парсинг JSON (требует плагин Pipeline Utility Steps).
  • readYaml file: 'config.yaml' — парсинг YAML.
  • writeJSON file: 'out.json', json: data — запись JSON.

Тестирование и отчеты

  • junit 'test-results/*.xml' — публикация результатов JUnit.
  • publishHTML target: [reportDir: 'docs', reportFiles: 'index.html'] — публикация HTML-отчёта.

Условия выполнения (when)

Блок when определяет, должен ли выполняться этап. Он может содержать одно или несколько условий.

Простые условия

  • branch 'main' — выполняется только в ветке main.
  • environment name: 'DEPLOY', value: 'true' — если переменная окружения равна значению.
  • expression { return params.DEPLOY == true } — произвольное выражение на Groovy.
  • not { branch 'dev' } — инверсия условия.
  • anyOf { branch 'main'; branch 'release' } — хотя бы одно из условий истинно.
  • allOf { branch 'main'; environment name: 'PROD', value: 'true' } — все условия истинны.

Расширенные условия

  • changeset "**/*.js" — выполняется, если изменены JS-файлы.
  • triggeredBy 'TimerTrigger' — запущено по расписанию.
  • buildingTag() — выполняется при сборке тега.
  • changelog 'regex' — проверка сообщений коммитов по регулярному выражению.

Пример:

stage('Deploy Prod') {
when {
allOf {
branch 'main'
environment name: 'ENV', value: 'prod'
expression { currentBuild.resultIsBetterOrEqualTo('SUCCESS') }
}
}
steps {
sh './deploy.sh'
}
}

Параллельное выполнение

Jenkins поддерживает параллельное выполнение этапов внутри одного stage.

Синтаксис:

stage('Test') {
parallel {
stage('Unit') {
steps { sh 'npm test' }
}
stage('Lint') {
steps { sh 'npm run lint' }
}
stage('Security') {
steps { sh 'npm audit' }
}
}
}

Особенности:

  • Все параллельные этапы получают одинаковое окружение.
  • Если один из этапов падает, остальные продолжают работать (если не указано иное).
  • Можно использовать failFast true, чтобы остановить все при первой ошибке.

Пример с failFast:

parallel {
failFast true
stage('A') { steps { sh '...' } }
stage('B') { steps { sh '...' } }
}

Обработка ошибок и повторы

Блок catchError

Позволяет перехватывать ошибки без остановки pipeline:

catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') {
sh 'might-fail.sh'
}

Повтор с логикой

def retries = 3
for (int i = 0; i < retries; i++) {
try {
sh 'flaky-command'
break
} catch (Exception e) {
if (i == retries - 1) throw e
sleep time: 10, unit: 'SECONDS'
}
}

Повторное использование кода

Shared Libraries

Позволяют выносить общую логику в отдельный Git-репозиторий.

Подключение в Jenkinsfile:

@Library('my-shared-lib') _

Функции из библиотеки вызываются как обычные Groovy-методы.

Шаблоны через load

Локальный скрипт:

def utils = load 'utils.groovy'
utils.sendNotification()

Файл utils.groovy должен возвращать объект:

def sendNotification() {
echo 'Sending notification...'
}
return this

Глобальные переменные

В Jenkins Pipeline доступен набор встроенных глобальных переменных, которые предоставляют информацию о текущем запуске, окружении и системе. Эти переменные доступны как в декларативном, так и в скриптовом pipeline.

Основные переменные (env)

Переменные из объекта env доступны в любом месте pipeline:

  • BUILD_NUMBER — номер текущей сборки.
  • BUILD_ID — идентификатор сборки (обычно совпадает с BUILD_NUMBER).
  • BUILD_TAG — строка вида jenkins-${JOB_NAME}-${BUILD_NUMBER}.
  • JOB_NAME — имя задания.
  • JOB_BASE_NAME — имя задания без пути (например, my-folder/my-jobmy-job).
  • BRANCH_NAME — имя ветки (в Multibranch Pipeline).
  • CHANGE_ID — идентификатор pull request (если применимо).
  • CHANGE_URL, CHANGE_TITLE, CHANGE_AUTHOR — метаданные pull request.
  • WORKSPACE — путь к рабочей директории на агенте.
  • NODE_NAME — имя агента, на котором выполняется этап.
  • EXECUTOR_NUMBER — номер исполнителя на узле.
  • JENKINS_HOME — путь к домашней директории Jenkins (только на master).
  • JENKINS_URL — URL-адрес Jenkins-сервера.
  • BUILD_URL — URL текущей сборки.
  • GIT_COMMIT — хеш последнего коммита.
  • GIT_BRANCH — имя ветки Git (например, origin/main).
  • GIT_URL — URL репозитория.

Пример использования:

echo "Сборка #${env.BUILD_NUMBER} для ветки ${env.BRANCH_NAME}"

Объект params

Содержит значения параметров, переданных при запуске задания:

if (params.DEPLOY_TO_PROD) {
sh './deploy.sh prod'
}

Объект currentBuild

Предоставляет доступ к метаданным текущей сборки:

  • currentBuild.result — результат (SUCCESS, FAILURE, UNSTABLE, ABORTED).
  • currentBuild.displayName — отображаемое имя сборки.
  • currentBuild.description — описание.
  • currentBuild.duration — длительность в миллисекундах.
  • currentBuild.rawBuild — низкоуровневый объект (требует разрешения в sandbox).

Пример:

post {
always {
echo "Сборка завершена со статусом: ${currentBuild.result}"
}
}

Объект scm

Автоматически определённый SCM-источник (в Multibranch Pipeline). Используется в checkout scm.


Параметры заданий: типы и допустимые значения

Параметры задаются в блоке parameters декларативного pipeline или через UI в Freestyle-проектах.

string

Текстовое поле.

string(
name: 'APP_VERSION',
defaultValue: '1.0.0',
description: 'Версия приложения'
)

booleanParam

Флажок.

booleanParam(
name: 'RUN_TESTS',
defaultValue: true,
description: 'Запускать ли тесты?'
)

choice

Выпадающий список.

choice(
name: 'ENVIRONMENT',
choices: ['dev', 'stage', 'prod'],
description: 'Целевая среда'
)

text

Многострочное текстовое поле.

text(
name: 'DEPLOY_NOTES',
defaultValue: 'Нет комментариев',
description: 'Заметки для деплоя'
)

password

Поле для ввода пароля (значение маскируется в логах).

password(
name: 'API_KEY',
defaultValue: '',
description: 'Секретный ключ API'
)

file

Позволяет загрузить файл при запуске (ограничено; работает только в Web UI, не в pipeline-as-code напрямую).

Примечание: в pipeline-файле fileParam не поддерживается напрямую. Для загрузки файлов требуется использование Freestyle-проекта или внешних механизмов (например, через API).


Безопасность и Groovy Sandbox

Jenkins по умолчанию запускает pipeline-скрипты в sandbox-режиме — ограниченной среде выполнения, которая блокирует вызов потенциально опасных методов Groovy.

Что запрещено в sandbox:

  • Прямой вызов new File(...), new ProcessBuilder(...).
  • Доступ к System.exit(), Runtime.exec().
  • Использование getClass(), evaluate(), this.class.
  • Прямой доступ к java.lang-классам без явного разрешения.

Как обойти ограничения:

  1. Администратор Jenkins может одобрить сигнатуры методов через Script Approval (веб-интерфейс → Manage Jenkins → In-process Script Approval).
  2. Использовать Shared Libraries, помеченные как «trusted» — они выполняются вне sandbox.
  3. Писать логику с использованием только разрешённых шагов (sh, readFile, writeFile и т.д.).

Рекомендации:

  • Избегайте прямого вызова Java/Groovy-методов.
  • Используйте встроенные шаги (sh, bat, powershell) для взаимодействия с системой.
  • Храните секреты в Credentials Store, а не в коде.

Jenkins Configuration as Code (JCasC)

JCasC — это способ управления конфигурацией Jenkins через YAML-файл, а не через веб-интерфейс.

Включение JCasC:

  1. Установите плагин Configuration as Code.
  2. Укажите путь к YAML-файлу через переменную окружения CASC_JENKINS_CONFIG или системное свойство.
  3. Jenkins загрузит конфигурацию при старте.

Пример jenkins.yaml:

jenkins:
systemMessage: "Автоматизированный CI/CD сервер"
numExecutors: 2
scmCheckoutRetryCount: 3

securityRealm:
local:
allowsSignup: false
users:
- id: "admin"
password: "${ADMIN_PASSWORD}"

authorizationStrategy:
globalMatrix:
permissions:
- "Overall/Administer:admin"
- "Job/Build:authenticated"
- "Job/Read:anonymous"

nodes:
- permanent:
name: "linux-agent"
remoteFS: "/home/jenkins"
launcher:
ssh:
host: "192.168.1.10"
port: 22
credentialsId: "ssh-agent-key"

credentials:
system:
domainCredentials:
- credentials:
- string:
scope: GLOBAL
id: "docker-hub-password"
secret: "${DOCKER_HUB_PASSWORD}"
description: "Пароль от Docker Hub"

jobs:
- script: >
pipelineJob('example-app') {
definition {
cpsScm {
scriptPath('Jenkinsfile')
scm {
git('https://github.com/user/repo.git', 'main')
}
}
}
}

Преимущества JCasC:

  • Конфигурация версионируется вместе с кодом.
  • Возможность воспроизводимого развёртывания.
  • Устранение «ручной настройки» на продакшен-сервере.

Переменные окружения в JCasC:

Используйте ${VAR_NAME} для подстановки значений из окружения. Например, ${ADMIN_PASSWORD} будет заменён на значение переменной ADMIN_PASSWORD.