How can I print current branch (of parallel branches) I am running at

216 Views Asked by At

I got code that list all branches and stages for my pipeline

def build_jobs = [:]
build_jobs['1'] = {
    node('builder'){
        stage('A'){
            sh 'echo 1'
            printMyStage()
        }
        stage('B'){
           printMyStage()
           "error"
        }
    }
}
build_jobs['2'] = {
    node('builder'){
        printMyStage()
        sh 'echo 2'
    }
}
build_jobs['3'] = {
    node('builder'){
        stage('A'){
            printMyStage()
            sh 'echo 3'
        }
        stage('B'){
            printMyStage()
        }
    }
}
parallel build_jobs

at the beginning of the run I am getting the following prints:

[Pipeline] parallel
[Pipeline] { (Branch: 1)
[Pipeline] { (Branch: 2)
[Pipeline] { (Branch: 3)

How can I reach the variable that has the branch name so the printMyStage() function will print the branch it was running from?

For current code the output will be:

Branch: 1
Branch: 1
Branch: 2
Branch: 3
Branch: 3

I also tried to use PipelineNodeGraphVisitor( currentBuild.rawBuild ) but without success

1

There are 1 best solutions below

2
zett42 On

You can get the head FlowNode for the current thread via undocumented CpsThread.current().head. Using FlowNode.getEnclosingBlocks() you can get the parent blocks and with some conditions you can determine the branch nodes.

Complete scripted pipeline example with nested parallel branches:

import org.jenkinsci.plugins.workflow.cps.CpsThread
import org.jenkinsci.plugins.workflow.graph.FlowNode
import org.jenkinsci.plugins.workflow.actions.LabelAction
import org.jenkinsci.plugins.workflow.actions.ThreadNameAction

node {
    def build_jobs = [:]
    
    build_jobs['1'] = {
        stage('A'){
            printMyStage('#1.A')
        }
        stage('B'){
           printMyStage('#1.B')
        }
    }
    build_jobs['2'] = {
        
        def nestedParallel = [:]
        
        nestedParallel['3'] = {
            stage('A') {
                printMyStage('#3.A')
            }            
        }
        nestedParallel['4'] = {
            stage('A'){
                printMyStage('#4.A')
            }
            stage('B'){
                printMyStage('#4.B')
            }
        }
        
        parallel nestedParallel
    }
    
    parallel build_jobs
}

// Get list of enclosing branches from "parallel" statement for given FlowNode
@NonCPS
List<FlowNode> getEnclosingBranches(FlowNode node) {
    List<FlowNode> enclosingBlocks = new ArrayList<>()
    for (FlowNode enclosing : node.getEnclosingBlocks()) {
        if (enclosing != null && enclosing.getAction(LabelAction.class) != null) {
            if (enclosing.getAction(ThreadNameAction.class) != null) {
                enclosingBlocks.add(enclosing)
            }
        }
    }

    return enclosingBlocks
}

// Print current branch name(s)
void printMyStage( String prefix ) {
    def branches = getEnclosingBranches( CpsThread.current().head.get() )
    if( branches ) {
        echo "$prefix ${branches.displayName}"
    }
}

Output (the order is random because of parallelism):

#1.A [Branch: 1]
#3.A [Branch: 3, Branch: 2]
#4.A [Branch: 4, Branch: 2]
#1.B [Branch: 1]
#4.B [Branch: 4, Branch: 2]

The function printMyStage() lists the names of all parent branches. If you only need immediate parent, use branches[0].displayName.