在管道工作流程中使用Jenkins'Mailer'

rke*_*lty 37 jenkins jenkins-plugins jenkins-pipeline

我想利用Jenkins 现有的Mailer插件来Jenkinsfile定义管道构建作业.鉴于以下简单的失败脚本,我希望每个版本都有一封电子邮件.

#!groovy

stage 'Test'
node {
    try {
        sh 'exit 1'
    } finally {
        step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: 'me@me.com', sendToIndividuals: true])
    }
}
Run Code Online (Sandbox Code Playgroud)

构建的输出是:

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
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,它确实记录了它step在失败后立即执行管道,但没有生成电子邮件.

在其他自由式工作中发送电子邮件,利用mailer工作正常,只需通过管道工作调用.

这与Jenkins 2.2和邮件程序1.17一起运行.

我应该使用不同的机制来调用失败的构建电子邮件吗? 我不需要mail步骤的所有开销,只需要关于故障和恢复的通知.

izz*_*kil 62

在管道中失败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: 'me@me.com', sendToIndividuals: true])
    }
}
Run Code Online (Sandbox Code Playgroud)

整个管道都包含着Jenkins提供的异常处理程序,这就是为什么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: 'me@me.com', sendToIndividuals: true])
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您不需要重新抛出可以使用的异常catchError.它是一个内置的Pipeline,可捕获其范围内的任何异常,将其打印到控制台并设置构建状态.例:

stage 'Test'
node {
    catchError {
        sh 'exit 1'
    } 
    step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: 'me@me.com', sendToIndividuals: true])
}
Run Code Online (Sandbox Code Playgroud)


Wil*_*hes 28

除了izzekil的出色答案之外,您可能希望根据提交作者选择电子邮件收件人.您可以使用email-ext执行此操作(基于其管道示例):

step([$class: 'Mailer',
      notifyEveryUnstableBuild: true,
      recipients: emailextrecipients([[$class: 'CulpritsRecipientProvider'],
                                      [$class: 'RequesterRecipientProvider']])])
Run Code Online (Sandbox Code Playgroud)

如果您使用的是最近的email-ext(2.50 +),则可以在管道中使用它:

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

如果你没有使用声明性的Jenkins文件,那么你需要把checkout scmJenkins找到提交者.见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'
    }
}
Run Code Online (Sandbox Code Playgroud)

  • Mailer参数`sendToIndividuals:true`是不是已经向提交作者发送了一封电子邮件? (2认同)

And*_*ndi 14

我认为在jenkins管道中发送邮件通知的更好方法是使用jenkins文档中描述的管道的post部分,而不是使用try catch:

pipeline {
  agent any
    stages {
      stage('whatever') {
        steps {
          ...
        }
      }
    }
    post {
        always {
          step([$class: 'Mailer',
            notifyEveryUnstableBuild: true,
            recipients: "example@example.com",
            sendToIndividuals: true])
        }
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)