在Jenkins管道中构建期间访问阶段名称

45

假设我们有以下的 Jenkinsfile:

stage name: "Cool stage"
    sh 'whoami'
stage name: "Better stage"
    def current_stage = getCurrentStageName()
    echo "CONGRATULATIONS, you are on stage: $current_stage"

问题是如何实现getCurrentStageName()方法。我知道可以使用currentBuild.rawBuild来访问构建运行时,但如何从那个点获取阶段名称呢?

我需要这个信息用于邮件通知的一些自定义设置,以便我始终能够捕获失败的阶段名称并将其包含在电子邮件正文中。


3
你找到答案了吗?我现在也在寻找同样的东西。 - Craigt
4
不是真正的答案,而是一种解决方法。你可以创建一种包装器,它会接受阶段名称,将其写入全局变量并调用“stage”。 - Aleks
4个回答

46

自Jenkins 2.3版本起,你现在可以以内置的方式完成这个操作。像这样:

steps {
    updateGitlabCommitStatus name: STAGE_NAME, state: 'running'
    echo '${STAGE_NAME}'
}

更多信息请参见:https://issues.jenkins-ci.org/browse/JENKINS-44456


非常顺利,谢谢(需要将其添加到他们的文档中!) - mim
1
如果我们能够获取stageName和stageResult,那就太好了。 - Frank Escobar

12

这应该可以在共享管道库中工作:

#!/usr/bin/env groovy

import hudson.model.Action;

import org.jenkinsci.plugins.workflow.graph.FlowNode
import org.jenkinsci.plugins.workflow.cps.nodes.StepStartNode
import org.jenkinsci.plugins.workflow.actions.LabelAction


def getStage(currentBuild){
    def build = currentBuild.getRawBuild()
    def execution = build.getExecution()
    def executionHeads = execution.getCurrentHeads()
    def stepStartNode = getStepStartNode(executionHeads)

    if(stepStartNode){
        return stepStartNode.getDisplayName()
    }
}

def getStepStartNode(List<FlowNode> flowNodes){
    def currentFlowNode = null
    def labelAction = null

    for (FlowNode flowNode: flowNodes){
        currentFlowNode = flowNode
        labelAction = false

        if (flowNode instanceof StepStartNode){
            labelAction = hasLabelAction(flowNode)
        }

        if (labelAction){
            return flowNode
        }
    }

    if (currentFlowNode == null) {
        return null
    }

    return getStepStartNode(currentFlowNode.getParents())
}

def hasLabelAction(FlowNode flowNode){
    def actions = flowNode.getActions()

    for (Action action: actions){
        if (action instanceof LabelAction) {
            return true
        }
    }

    return false
}

def call() {
    return getStage(currentBuild)
}

使用示例:

node {
    stage('Stage One'){
        echo getCurrentStage()
    }

    stage('Stage Two'){
        echo getCurrentStage()
    }
}

1
我已经成功修改了你的脚本,以便获取先前执行阶段的信息。你知道如何获取这些先前阶段的构建结果吗? - andsens
明白了!http://javadoc.jenkins.io/plugin/pipeline-rest-api/com/cloudbees/workflow/flownode/FlowNodeUtil.html#getStatus-org.jenkinsci.plugins.workflow.graph.FlowNode- - andsens
2
我制作了一个示例来获取阶段结果: https://gist.github.com/GuillaumeSmaha/fdef2088f7415c60adf95d44073c3c88 - GuillaumeS
太棒了,我还能提取parallel()分支的名称。 - Joerg S
这些函数未被列入沙盒使用白名单。 - haridsv

5
Aleks的解决方法很好,我认为值得分享代码。
node ("docker") {
    def sendOk = {
        String stage -> slackSend color: 'good', message: stage + " completed, project - ${env.JOB_NAME}:1.0.${env.BUILD_NUMBER}"
    }
    def sendProblem = {
        String stage, error -> slackSend color: 'danger', message: stage + " did not succeed, project - ${env.JOB_NAME}:1.0.${env.BUILD_NUMBER}, error: ${error}, Find details here: ${env.BUILD_URL}"
    }
    def exec = {
        work, stageName -> 
            stage (stageName) {
                try {
                    work.call();
                    sendOk(stageName)
                }
                catch(error) {
                    sendProblem(stageName, error)
                    throw error
                }
            }
    }
    exec({
        git credentialsId: 'github-root', url: 'https://github.com/abc'
        dir ('src') {
            git credentialsId: 'github-root', url: 'https://github.com/abc-jenkins'
        }
        sh "chmod +x *.sh"
    }, "pull")
    exec({ sh "./Jenkinsfile-clean.sh \"1.0.${env.BUILD_NUMBER}\"" }, "clean")
    exec({ sh "./Jenkinsfile-unit.sh \"1.0.${env.BUILD_NUMBER}\"" }, "unit")
    exec({ sh "./Jenkinsfile-build.sh \"1.0.${env.BUILD_NUMBER}\"" }, "build")
    exec({ sh "./Jenkinsfile-dockerize.sh \"1.0.${env.BUILD_NUMBER}\"" }, "dockerize")
    exec({ sh "./Jenkinsfile-push.sh \"1.0.${env.BUILD_NUMBER}\"" }, "push")
    exec({ sh "./Jenkinsfile-prod-like.sh \"1.0.${env.BUILD_NUMBER}\"" }, "swarm")
}

0
作为解决方法,在失败的电子邮件中,我会包含一个指向“Pipeline Steps”页面的链接。该页面清晰地显示了每个步骤的绿色和红色球,使得电子邮件接收者不仅可以确定阶段,还可以确定失败的具体步骤。
在下面的示例电子邮件正文中,“FlowGraphTable”链接指向“Pipeline Steps”页面:
def details = """<p>Job '${env.JOB_NAME}', build ${env.BUILD_NUMBER} result was ${buildStatus}.
  Please scrutinize the build and take corrective action.</p>
  <p>Quick links to the details:
  <ul>
    <li><a href="${env.JOB_URL}">${env.JOB_NAME} job main page</a></li>
    <li><a href="${env.BUILD_URL}">Build ${env.BUILD_NUMBER} main page</a></li>
    <ul>
      <li><a href="${env.BUILD_URL}console">Console output</a></li>
      <li><a href="${env.BUILD_URL}changes">Git changes</a></li>
      <li><a href="${env.BUILD_URL}flowGraphTable">Pipeline steps</a>.
          This page will show you which step failed, and give you access
          to the job workspace.</li>
    </ul>
  </ul></p>"""

这是我实现的notifyBuild()的一部分,BitwiseMan在他的文章Sending Notifications in Pipeline中提出。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接