Уведомления и отчёты: email, Slack, Telegram, HTML

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

Уведомления и отчёты: email, Slack, Telegram, HTML

Сообщение 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
Сборка упала в 03:17 ночи, а узнал ты об этом в 10:40, когда тимлид написал "почему прод не катится". Знакомо? Конвейер может быть идеально настроен, но если о его результатах никто вовремя не узнаёт - половина пользы CI/CD испаряется. Обратная связь о сборках это не украшение, а часть контура. В этом уроке разберём, как настроить jenkins уведомления так, чтобы они приходили туда, где люди реально работают - в почту, в Slack, в Telegram - и при этом несли смысл, а не просто "Build #482 FAILED".

Костяк темы взят из главы 4 книги Ластера, но синтаксис и инструменты освежены под 2026 год. На момент написания актуальная Jenkins LTS - 2.555.1 (требует Java 21 или 25), и все шаги ниже работают на ней. Стандарт по умолчанию - declarative pipeline, именно в его post-секции и живёт вся логика оповещений.

Где живут уведомления: post-секция как контур обратной связи

Главная идея проста: уведомление - это реакция на исход сборки, а не отдельный шаг внутри stages. Поэтому отправку выносят в блок post, который выполняется после всех стадий и умеет ветвиться по статусу. Ключевые условия, которые тебе понадобятся:
  • always - выполняется всегда, что бы ни случилось. Сюда вешают cleanup и публикацию отчётов.
  • success - только при зелёной сборке.
  • failure - сборка упала. Главный кандидат на громкое оповещение.
  • unstable - сборка прошла, но тесты или линтер пометили её нестабильной.
  • changed - статус изменился относительно прошлой сборки (была красной - стала зелёной, или наоборот). Идеально, чтобы не спамить.
  • fixed и regression - частные случаи changed: починили после падения / сломали после успеха.
Вот скелет, на который мы будем навешивать каналы:

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

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                sh './gradlew clean build'
            }
        }
    }
    post {
        failure {
            echo 'Сборка упала - шлём громкое уведомление'
        }
        fixed {
            echo 'Починились после красной - сообщаем, что отпустило'
        }
    }
}
Изображение

Email через emailext: содержательные письма, а не "FAILED"

Базовый шаг mail умеет только отправить текст. Для нормальной работы ставят плагин Email Extension - он даёт шаг emailext с шаблонами, провайдерами получателей и вложениями. Именно так делают jenkins email-оповещения, которые не стыдно показать команде.

Самое полезное в emailext - recipientProviders. Вместо хардкода адресов ты говоришь "пиши тем, кто закоммитил в этот билд" через developers(), плюс инициатору запуска через requestor(). Лог сборки можно приложить вложением через attachLog. Письмо стоит слать при падении и при unstable:

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

post {
    unsuccessful {
        emailext(
            subject: "[Jenkins] ${currentBuild.currentResult}: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
            body: """\
Статус: ${currentBuild.currentResult}
Job:    ${env.JOB_NAME}
Билд:   #${env.BUILD_NUMBER}
Лог:    ${env.BUILD_URL}console

Последний коммит сломал сборку. Подробности во вложении.""",
            attachLog: true,
            compressLog: true,
            recipientProviders: [developers(), requestor(), culprits()]
        )
    }
}
Условие unsuccessful ловит и failure, и unstable, и aborted - удобно. Провайдер culprits() добавляет тех, чьи коммиты накопились с момента последней успешной сборки - полезно, когда виноватого с одного коммита не вычислить. Для красивых писем emailext поддерживает HTML-шаблоны (Jelly или Groovy templates), но для старта хватит и plain text с прямой ссылкой на лог.

Slack и Telegram: jenkins notifications прямо в рабочий чат

Почту читают не все и не сразу. Поэтому боевой канал - командный мессенджер. Для Slack ставится официальный плагин Slack Notification, в нём настраивается workspace и токен бота, а в пайплайне появляется шаг slackSend. Связка jenkins slack - это де-факто стандарт: цветной аттач, ссылка на сборку, упоминание виновника.

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

post {
    failure {
        slackSend(
            channel: '#ci-alerts',
            color: 'danger',
            message: ":fire: Упала сборка *${env.JOB_NAME}* #${env.BUILD_NUMBER}\n" +
                     "Коммит: ${env.GIT_COMMIT?.take(8)} | <${env.BUILD_URL}console|смотреть лог>"
        )
    }
    fixed {
        slackSend(
            channel: '#ci-alerts',
            color: 'good',
            message: ":white_check_mark: Починили *${env.JOB_NAME}* #${env.BUILD_NUMBER}"
        )
    }
}
Цвета: good (зелёный), warning (жёлтый, под unstable), danger (красный) или любой hex вроде '#AA1100'. Если нужно ткнуть конкретного человека, плагин умеет резолвить Slack-юзера по email через slackUserIdFromEmail - и ты вставляешь <@$userId> прямо в message.

Mattermost работает почти так же: ставится плагин Mattermost Notification, шаг называется mattermostSend, параметры channel/color/message повторяют Slack один в один. Если у вас self-hosted Mattermost - мигрировать с примеров Slack тривиально.

С Telegram сложнее: стабильного популярного плагина нет, и надёжнее всего слать через Bot API курлом. Создаёшь бота у @BotFather, узнаёшь chat_id, кладёшь токен в Credentials и дёргаешь sendMessage. Так jenkins telegram заводится за пять минут и не зависит от состояния очередного заброшенного плагина:

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

post {
    failure {
        withCredentials([string(credentialsId: 'tg-bot-token', variable: 'TG_TOKEN')]) {
            sh '''
                curl -s -X POST \
                  "https://api.telegram.org/bot${TG_TOKEN}/sendMessage" \
                  -d chat_id="-1001234567890" \
                  -d parse_mode="HTML" \
                  --data-urlencode "text=<b>FAILED</b> ${JOB_NAME} #${BUILD_NUMBER}
${BUILD_URL}console"
            '''
        }
    }
}
Если ставить curl на агентах не хочется, тот же запрос делается шагом httpRequest из HTTP Request Plugin - чистый Groovy без шелла. Токен всегда через withCredentials, никогда в открытом виде в Jenkinsfile.

HTML-отчёты через publishHTML: тесты и покрытие под рукой

Уведомление говорит "что-то сломалось", а отчёт показывает "что именно". JaCoCo-покрытие, Allure, отчёт линтера или results любого тест-раннера - это HTML, который генерится в workspace и пропадает после сборки. Чтобы он остался и был доступен ссылкой из карточки билда, ставят HTML Publisher Plugin и шаг publishHTML. Его место - в post { always }, потому что отчёт нужен и при провале (особенно при провале):

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

post {
    always {
        publishHTML(target: [
            allowMissing: false,
            alwaysLinkToLastBuild: true,
            keepAll: true,
            reportDir: 'build/reports/tests/test',
            reportFiles: 'index.html',
            reportName: 'Test Report',
            reportTitles: 'Результаты тестов'
        ])
    }
}
keepAll: true хранит отчёты всех сборок, а не только последней - удобно сравнивать. allowMissing: false уронит сборку, если отчёта нет (защита от "тесты молча не сгенерили results"). Ссылка появится в меню сборки. А в Slack/Telegram стоит слать прямой URL на этот отчёт - человек кликает и сразу видит, какой тест красный.

Типичные грабли
  • Спам зелёными сборками. Если слать success на каждый билд, через неделю канал замьютят, и красные сборки утонут. Шли по failure и fixed (или changed) - команде важен момент поломки и починки, а не рутинный успех.
  • Бессодержательные сообщения. "Build #482 failed" бесполезно. В тексте должно быть: что за job, кто закоммитил, прямая ссылка на лог/отчёт. Иначе человек всё равно лезет в Jenkins руками.
  • Падение пайплайна из-за самого уведомления. Если Slack недоступен, slackSend кинет исключение и сборка станет красной уже из-за нотификации. Оборачивай отправку в try/catch (в scripted) или принимай, что post-условие может частично упасть.
  • Секреты в открытом виде. Токен Telegram или Slack webhook в Jenkinsfile - это утечка в Git. Всегда Credentials + withCredentials.
  • CSP режет HTML-отчёт. Из-за Content Security Policy сложные отчёты с inline-стилями и JS могут отображаться кривrecently. Современные отчёты (Allure) с этим дружат, но если видишь голый HTML без стилей - копай в сторону CSP-заголовков Jenkins.
Мини-лаба
  • Возьми любой declarative-пайплайн и добавь блок post с условиями failure, fixed и always.
  • В failure повесь emailext с recipientProviders: [developers(), requestor()] и attachLog: true. Намеренно сломай сборку (sh 'exit 1') и проверь письмо.
  • Заведи Telegram-бота через @BotFather, положи токен в Credentials, добавь отправку через curl в post { failure }. Убедись, что в сообщении есть JOB_NAME, BUILD_NUMBER и ссылка.
  • Сгенерь любой HTML-отчёт (хоть echo в файл index.html), опубликуй через publishHTML в post { always } и открой его из карточки сборки.
  • Сравни, как то же самое делается в GitLab CI (rules + integrations) и GitHub Actions (if: failure() + action для Slack) - заметишь, что идея post-условий универсальна.
Контрольные вопросы
  • Почему отправку уведомлений размещают в post-секции, а не внутри stages? Чем отличаются условия failure, changed и fixed?
  • Что делают recipientProviders developers() и culprits() в emailext и когда какой выбрать?
  • Как безопасно передать токен Telegram-бота в шаг curl, не раскрывая его в Jenkinsfile?
  • Почему publishHTML логично ставить в post { always }, а не в success, и за что отвечает флаг keepAll?
Итог

Хороший контур уведомлений - это failure и fixed в командный чат, развёрнутое письмо разработчику-виновнику и HTML-отчёт ссылкой из карточки. Slack и Mattermost через готовые плагины, Telegram через Bot API курлом, почта через emailext с провайдерами получателей. Главное правило: не спамить зелёными сборками и класть в каждое сообщение смысл - что упало, кто виноват, куда смотреть. Тогда CI/CD реально экономит время, а не добавляет ещё один источник шума.
👍2 ❤️3 🔥 😄 🤔
Аватара пользователя
silentgoblin
Сообщения: 1
Зарегистрирован: 14 май 2026, 07:47

Re: Уведомления и отчёты: email, Slack, Telegram, HTML

Сообщение silentgoblin »

А мы сначала слали success на каждый билд, через неделю весь отдел замьютил канал. Перешли на failure + fixed и сразу стало по делу, спасибо что подтвердили что так и надо.
👍 ❤️ 🔥 😄 🤔
Аватара пользователя
kernel123
Сообщения: 1
Зарегистрирован: 12 май 2026, 06:55

Re: Уведомления и отчёты: email, Slack, Telegram, HTML

Сообщение kernel123 »

По телеге вопрос: а если curl на агенте не установлен, httpRequest реально нормально работает с parse_mode HTML? Или там с экранированием возни больше?
👍 ❤️ 🔥 😄 🤔
Ответить
← Предыдущая глава
Безопасность сценариев: Groovy sandbox и Vault
Следующая глава →
Blue Ocean и интерфейс Jenkins в 2026

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

Поделиться темой: ✈ Telegram VK

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

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

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