在Jenkins Pipeline中获取步骤ID,以链接到BlueOcean或Pipeline Steps视图(flowGraphTable)

时间:2019-01-21 10:11:21

标签: jenkins pipeline jenkins-blueocean

鉴于詹金斯管道运行了一系列步骤,其中一些在parallel块内,有什么方法可以在管道内获取给定步骤或最新步骤的流ID。步骤?

什么是流ID?如果您查看“管道运行”作业,则可以看到指向“ flowGraphTable/”的“管道步骤”链接。那里有指向特定工作步骤的链接,例如execution/node/113/。这些似乎代表FlowNode

有什么方法可以从管道中获取这些ID,以生成链接等?

特别是我想获得到我的并行分支的子流的链接,以便可以链接到它们的BlueOcean视图。 (内置的Jenkins视图是无用的,因为它不显示子树)。

我可以看到BlueOcean链接对应于/ execution /链接,它们具有相同的id值。如果我的管道分支是myjob/9/execution/node/78/,那么在blueocean上它将是jobname/9/pipeline/78

但是,如果我想使用构建摘要插件或类似的东西来生成链接并将其添加到构建结果页面中,如何获得该ID?

3 个答案:

答案 0 :(得分:1)

这将获得封闭节点步骤的工作空间链接。 您可以使用.getId()而不是.url获取ID 在使用节点{....}时,这适用于我的情况,但在声明性步骤或内部并行步骤中使用时可能需要一些改进。

def getNodeWsUrl(flowNode = null) {
    if(!flowNode) {
        flowNode = getContext(org.jenkinsci.plugins.workflow.graph.FlowNode)
    }
    if(flowNode instanceof org.jenkinsci.plugins.workflow.cps.nodes.StepStartNode && flowNode.typeFunctionName == 'node') {
        // Could also check flowNode.typeDisplayFunction == 'Allocate node : Start'
        return "/${flowNode.url}ws/"
    }

    return flowNode.parents.findResult { getNodeWsUrl(it) }
}

答案 1 :(得分:0)

您可以回显或指定可以使用的节点名称,而不是获取并行作业的步骤ID。

答案 2 :(得分:0)

我正在努力解决类似的用例,并设法找到了适合我的解决方案。 https://issues.jenkins-ci.org/browse/JENKINS-28119可能是关于该问题的有趣读物。最终,它为我指明了一个正确的方向。

除了管道和管道阶段视图插件外,我还必须在我们的Jenkins服务器上安装HTTP请求插件(https://wiki.jenkins.io/display/JENKINS/HTTP+Request+Plugin)和管道实用程序步骤插件(用于解析JSON,https://wiki.jenkins.io/display/JENKINS/Pipeline+Utility+Steps+Plugin)。我不确定还需要其他哪些插件。

这是我的工作示例,只缺少正在评估的阶段:

#!groovy

pipeline {
    agent any

    stages {
        stage('Test') {
            steps {
                script {
                    def responseRun = httpRequest(
                        //consoleLogResponseBody: true,
                        contentType: 'APPLICATION_JSON',
                        httpMode: 'GET',
                        url: BUILD_URL + 'wfapi',
                        validResponseCodes: '200'
                    )
                    def runJson = readJSON text: responseRun.getContent()
                    def headNodeUrl = ''
                    runJson.stages.each {
                        if (it.name.toString() == 'Stage node label') {
                            // Found head node: it.id
                            headNodeUrl = BUILD_URL + 'execution/node/' + it.id.toString() + '/'
                        }
                    }
                    def responseNode = httpRequest(
                        contentType: 'APPLICATION_JSON',
                        httpMode: 'GET',
                        url: headNodeUrl + 'wfapi',
                        validResponseCodes: '200'
                    )
                    def nodeJson = readJSON text: responseNode.getContent()
                    def execNodeUrl = ''
                    nodeJson.stageFlowNodes.each {
                        if (it.name.toString() == 'Execution node label') {
                            // Found execution node: it.id
                            execNodeUrl = BUILD_URL + 'execution/node/' + it.id.toString() + '/log/'
                        }
                    }
                    echo execNodeUrl
                }
            }
        }
    }
}
我假设

BUILD_URL是由詹金斯(Jenkins)提供的全局环境变量。在我的完整脚本中,我有一个stage('Stage node label') { ... },其中包含一个语句bat label: 'Execution node label', script: ...,其日志URL将使用echo构建并打印。

结果是一个类似http://myjenkinsserver.org:8080/job/some_folder/job/my_job_name/181/execution/node/50/log/

的URL

我认为在示例中使用each可能并不理想,因为在第一个比赛之后我无法中止使用它。同样,我也没有设法将httpRequestreadJSON封装到类方法之类的东西中,因为我无法弄清楚readJSON的返回类型。任何提示表示赞赏。

我希望这会有所帮助。

欢呼