Given a Jenkins pipeline that runs a series of steps, some within parallel
blocks, is there any way to obtain within the pipeline the Flow id of a given step or the most recent step?
What's a Flow ID? If you look at a Run of your Pipeline job you can see a "Pipeline Steps" link that points to flowGraphTable/
. There you have links to specific job steps like execution/node/113/
. These seem to represent a FlowNode
.
Is there any way to get these IDs from within the pipeline, for generating links etc?
In particular I want to get a link to the sub-Flow for my parallel branches so I can link to the BlueOcean views of them. (The builtin Jenkins view is useless because it doesn't show a subtree).
I can see that the BlueOcean links correspond to the /execution/ links, they have the same id value. If my pipeline branch is myjob/9/execution/node/78/
then on blueocean it'll be jobname/9/pipeline/78
.
But how do I get that ID if I want to use the build summary plugin or similar to generate the links and add them to the build results page?
I was struggling with the a similar use case and managed to find a solution that is working for me. This https://issues.jenkins-ci.org/browse/JENKINS-28119 might be an interesting read on the issue. It eventually pointed me in a good direction.
Besides the Pipeline and Pipeline Stage View Plugin, I had to install the HTTP Request Plugin (https://wiki.jenkins.io/display/JENKINS/HTTP+Request+Plugin) and the Pipeline Utility Steps Plugin (for parsing JSON, https://wiki.jenkins.io/display/JENKINS/Pipeline+Utility+Steps+Plugin) on our Jenkins server. I am not sure which other plugins might be required.
Here is my working example, only missing the stages being evaluated:
#!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
is a global environment variable, supplied by Jenkins, I assume. In my full script I have a stage('Stage node label') { ... }
containing a statement bat label: 'Execution node label', script: ...
whose log URL will be constructed and printed with echo
.
The result is a URL like http://myjenkinsserver.org:8080/job/some_folder/job/my_job_name/181/execution/node/50/log/
I think the use of each
in my example might not be ideal, since I cannot abort it after the first match. Also I didn't manage to encapsulate the httpRequest
and readJSON
into a class method or something because I couldn't figure out the return type of readJSON
. Any hints are appreciated.
I hope this helps.
Cheers
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With