【问题标题】:How to send notifications in Jenkins pipeline when build recovers?构建恢复时如何在 Jenkins 管道中发送通知?
【发布时间】:2017-03-03 11:40:49
【问题描述】:

我想在作业恢复时从我的 Jenkins 管道构建中发送通知。这意味着当前构建成功而上一次构建错误(失败、中止等)。

我知道如何发送通知。我认为我的问题归结为如何检查以前构建的状态,但我可能弄错了。

我尝试过“currentBuild.rawBuild.getPreviousBuild()?.getResult()”,但得到异常“org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not allowed to use method org.jenkinsci.plugins.workflow .support.steps.build.RunWrapper getRawBuild”。如果我关闭沙箱,它应该可以工作。沙盒可以吗?

【问题讨论】:

  • 您是否尝试过手动批准方法签名?在Jenkins > Administer > In-Process Script Approval
  • 我没试过。我无法从任何地方找到管理链接。我也不是 Jenkins 管理员。 macg33zr 提供的解决方案很好,因为它无需任何特殊调整即可工作。
  • 确实如此,但它只适用于声明式管道,不适用于经典管道
  • 您还可以使用像 CatLight build notifier 这样的专用工具,它将向每个团队成员显示当前的构建状态和历史记录。

标签: jenkins notifications jenkins-pipeline


【解决方案1】:

我找到了另一个可行的解决方案,它不需要您手动跟踪构建结果。虽然,它需要使用脚本元素:(

pipeline {
  agent any
  post {
    success {
      script {
        if (currentBuild.getPreviousBuild() && 
            currentBuild.getPreviousBuild().getResult().toString() != "SUCCESS") {
          echo 'Build is back to normal!'
        }
      }
    }
  }
}

【讨论】:

  • 我最喜欢这个解决方案,因为它易于阅读并且与构建本身完全无关。
  • 这是一个很好的解决方案,但是,第一次运行作业时,脚本会给出异常:java.lang.NullPointerException: Cannot invoke method getResult() on null object
  • @DavidA 也注意到了这一点,添加了一个空检查。
【解决方案2】:

有趣的问题。您可以使用 post{} 部分的“已更改”部分在 Jenkins 声明式管道中执行此操作。但是您需要在作业中将 currentBuild.result 设置为 SUCCESS 或 FAILURE 并在 post 部分进行检查。就 Jenkins 而言,如果不在您的管道中跟踪它,似乎没有一种简单的方法可以获取当前的构建状态(失败、成功等)——除非我错过了一些微妙的东西。这是一个示例,您将在更改部分发送通知,它会检查成功:

pipeline {
    agent any

    parameters {
        string(name: 'FAIL',     defaultValue: 'false', description: 'Whether to fail')
    }

    stages {
        stage('Test') {

            steps {

                script {

                    if(params.FAIL == 'true') {
                        echo "This build will fail"
                        currentBuild.result = 'FAILURE'
                        error("Build has failed")
                    }
                    else {
                        echo "This build is a success"
                        currentBuild.result = 'SUCCESS'
                    }

                }
            }
        }
    }

    post {
        always  {
            echo "Build completed. currentBuild.result = ${currentBuild.result}"
        }

        changed {
            echo 'Build result changed'

            script {
                if(currentBuild.result == 'SUCCESS') {
                    echo 'Build has changed to SUCCESS status'
                }
            }
        }

        failure {
            echo 'Build failed'
        }

        success {
            echo 'Build was a success'
        }
        unstable {
            echo 'Build has gone unstable'
        }
    }
}

--比尔

【讨论】:

  • 我试试看。设置当前的构建状态完全没问题。我的脚本应该知道它何时成功或失败。
  • 这很好用。您知道脚本化管道环境是否以及如何实现?我从文档中了解到脚本化环境比声明性更强大,但它缺乏可能的文档。
  • 我还没有弄清楚如何在脚本化管道中执行此操作。这就是为什么我在用脚本完成了大量工作后迅速转向声明式管道模式的原因——声明式管道具有构建后处理,这对我来说是一个杀手级应用程序。我发现我可以在共享库中或管道部分之外使用脚本部分和 groovy 代码在声明性方面做很多事情。如果你去 GitHub 上的声明式管道的开发人员单元测试,他们有很多例子:github.com/jenkinsci/pipeline-model-definition-plugin/tree/…
  • 我在声明性管道中使用 post { changed { notify that status changed} } 模型,但我真正想要的只是通知它已更改为成功。我总是通知失败,所以现在当它从成功变为失败时我们会得到重复。我试图找到一种在 post 块中获取当前构建状态的方法,但无法做到这一点。 currentBuild.result 仅在您自己管理和设置时才有效。我认为这是目前管道功能中的一个相当大的漏洞。
  • currentBuild.currentResult 为您提供管道的结果将是什么——在管道帖子部分中应该是准确的。
【解决方案3】:

类似于@Kolky 的回答,这将是“脚本化管道”的 sn-p,您使用“node{ stage1...stage2...etc }”:

    stage('Email') {
        if (currentBuild.getPreviousBuild().getResult().toString() != "SUCCESS") {
            echo 'Build is back to normal!'
            stage('Send build recovered email') {
                mail body: 'My build back to successful',
//                    from: '', replyTo: '',
                        subject: 'My build back to successful',
                        to: 'mymail@server.com'
            }

        }
    }

【讨论】:

  • 这种改进的 if 条件避免了 NPE,并且仅在构建状态从不成功变为成功时通知:if (currentBuild.currentResult == 'SUCCESS' && currentBuild.previousBuild?.result != "SUCCESS")
【解决方案4】:

或者,您可以将脚本逻辑移到管道之外(理想情况下 - 到 Jenkins shared pipeline library 以便可重复使用并保持管道清洁),这样您就不需要 script 块:

def sendNotification(buildStatus) {
  if (buildStatus != 'SUCCESS') {
    // Do nothing - only interested when status becomes GREEN
    return
  }

  mattermostSend "${env.JOB_NAME} has recovered! (<${env.BUILD_URL}|See the build>)"
}

pipeline {
  ...

  post {
    changed {
      sendNotification(currentBuild.currentResult)
    }
  }
}

【讨论】:

【解决方案5】:

随附的文档会有所帮助:

Pipeline Ref Card

【讨论】:

    【解决方案6】:

    macg33zr 给出了很好的答案。同时,还有一种更简单的方法可以在管道恢复后在声明性管道中执行某些步骤:post 部分中有一个新的fixed 条件。固定条件部分中的 post 步骤仅在“当前 Pipeline 或阶段的运行成功且前一次运行失败或不稳定的情况下”运行。 (详见Jenkins' declarative pipeline documentation)。

    pipeline {
        agent any
        stages {
            stage('Build') {
                steps {
                    echo 'Do Something that could fail the pipeline.'
                }
            }
        }
        post { 
            fixed { 
                echo 'Build is back to normal!'
            }
        }
    }
    

    如果你想发送通知,有几个 Jenkins 插件,例如 Slack。 Slack 的通知代码如下所示。

    pipeline {
        agent any
        stages {
            stage('Build') {
                steps {
                    echo 'Do Something that could fail the pipeline.'
                }
            }
        }
        post { 
            fixed { 
                slackSend channel: '#your-slack-target-channel',
                      color: 'good',
                      message: "The build is back to normal. :sweat_smile: The build _${currentBuild.fullDisplayName}_ was successful again.\nGo to pipeline: ${env.BUILD_URL}"
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-18
      • 2017-03-30
      • 1970-01-01
      相关资源
      最近更新 更多