Подтвердить что ты не робот

Использовать рабочий поток Jenkins 'Mailer'

Я хотел бы использовать существующий плагин Mailer от Jenkins в Jenkinsfile, который определяет задание сборки трубопровода. Учитывая следующий простой сбой script, я ожидал бы электронной почты на каждой сборке.

#!groovy

stage 'Test'
node {
    try {
        sh 'exit 1'
    } finally {
        step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: '[email protected]', sendToIndividuals: true])
    }
}

Результат сборки:

Started by user xxxxx
[Pipeline] stage (Test)
Entering stage Test
Proceeding
[Pipeline] node
Running on master in /var/lib/jenkins/jobs/rpk-test/workspace
[Pipeline] {
[Pipeline] sh
[workspace] Running shell script
+ exit 1
[Pipeline] step
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
ERROR: script returned exit code 1
Finished: FAILURE

Как вы можете видеть, он записывает, что он выполняет конвейер step сразу после сбоя, но никакие электронные письма не генерируются.

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

Это работает с Jenkins 2.2 и почтовой программой 1.17.

Есть ли другой механизм, с помощью которого я должен вызывать неработающие электронные письма? Мне не нужны все накладные расходы на этапе mail, просто нужны уведомления о сбоях и восстановлениях.

4b9b3361

Ответ 1

В отключенном конвейере sh не сразу устанавливает значение currentBuild.result в FAILURE, а его начальное значение - null. Следовательно, шаги сборки, основанные на статусе сборки, такие как Mailer, могут казаться некорректными.

Вы можете проверить это, добавив отладочную печать:

stage 'Test'
node {
    try {
        sh 'exit 1'
    } finally {
        println currentBuild.result  // this prints null
        step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: '[email protected]', sendToIndividuals: true])
    }
}

Весь этот конвейер завернут обработчиком исключений, предоставленным Дженкинсом, поэтому Jenkins отмечает, что сборка завершилась неудачей.

Итак, если вы хотите использовать Mailer, вам необходимо правильно поддерживать статус сборки. Например:

stage 'Test'
node {
    try {
        sh 'exit 1'
        currentBuild.result = 'SUCCESS'
    } catch (any) {
        currentBuild.result = 'FAILURE'
        throw any //rethrow exception to prevent the build from proceeding
    } finally {
        step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: '[email protected]', sendToIndividuals: true])
    }
}

Если вам не нужно восстанавливать исключение, вы можете использовать catchError. Это встроенный модуль Pipeline, который выхватывает любое исключение в своей области, печатает его в консоли и устанавливает статус сборки. Пример:

stage 'Test'
node {
    catchError {
        sh 'exit 1'
    } 
    step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: '[email protected]', sendToIndividuals: true])
}

Ответ 2

В дополнение к отличному ответу izzekil, вы можете пожелать выбрать получателей электронной почты на основе авторов фиксации. Вы можете использовать email-ext, чтобы сделать это (на основе их примеры конвейера):

step([$class: 'Mailer',
      notifyEveryUnstableBuild: true,
      recipients: emailextrecipients([[$class: 'CulpritsRecipientProvider'],
                                      [$class: 'RequesterRecipientProvider']])])

Если вы используете недавний email-ext (2.50+), вы можете использовать его в своем конвейере:

emailext(body: '${DEFAULT_CONTENT}', mimeType: 'text/html',
         replyTo: '$DEFAULT_REPLYTO', subject: '${DEFAULT_SUBJECT}',
         to: emailextrecipients([[$class: 'CulpritsRecipientProvider'],
                                 [$class: 'RequesterRecipientProvider']]))

Если вы не используете декларативный файл Jenkins, вам нужно поставить checkout scm, чтобы Дженкинс мог найти коммиттеров. См. JENKINS-46431.

Если вы все еще используете более старую версию email-ext, вы попадете в JENKINS-25267. Вы можете перевернуть свой собственный HTML-адрес электронной почты:

def emailNotification() {
    def to = emailextrecipients([[$class: 'CulpritsRecipientProvider'],
                                 [$class: 'DevelopersRecipientProvider'],
                                 [$class: 'RequesterRecipientProvider']])
    String currentResult = currentBuild.result
    String previousResult = currentBuild.getPreviousBuild().result

    def causes = currentBuild.rawBuild.getCauses()
    // E.g. 'started by user', 'triggered by scm change'
    def cause = null
    if (!causes.isEmpty()) {
        cause = causes[0].getShortDescription()
    }

    // Ensure we don't keep a list of causes, or we get
    // "java.io.NotSerializableException: hudson.model.Cause$UserIdCause"
    // see http://stackoverflow.com/a/37897833/509706
    causes = null

    String subject = "$env.JOB_NAME $env.BUILD_NUMBER: $currentResult"

    String body = """
<p>Build $env.BUILD_NUMBER ran on $env.NODE_NAME and terminated with $currentResult.
</p>

<p>Build trigger: $cause</p>

<p>See: <a href="$env.BUILD_URL">$env.BUILD_URL</a></p>

"""

    String log = currentBuild.rawBuild.getLog(40).join('\n')
    if (currentBuild != 'SUCCESS') {
        body = body + """
<h2>Last lines of output</h2>
<pre>$log</pre>
"""
    }

    if (to != null && !to.isEmpty()) {
        // Email on any failures, and on first success.
        if (currentResult != 'SUCCESS' || currentResult != previousResult) {
            mail to: to, subject: subject, body: body, mimeType: "text/html"
        }
        echo 'Sent email notification'
    }
}

Ответ 3

Я думаю, что лучший способ отправки почтовых уведомлений в конвейерах jenkins - использовать почтовый раздел конвейера, как описано в jenkins docs вместо этого использования try catch:

pipeline {
  agent any
    stages {
      stage('whatever') {
        steps {
          ...
        }
      }
    }
    post {
        always {
          step([$class: 'Mailer',
            notifyEveryUnstableBuild: true,
            recipients: "[email protected]",
            sendToIndividuals: true])
        }
      }
    }
  }
}