Jenkins declarative pipeline: find out triggering job
Asked Answered
T

3

5

We have a Jenkins job that uses a declarative pipeline.

This job can be triggered by different other builds.

In the declarative pipeline how can I find out which build has triggered the pipeline?

Tillietillinger answered 24/10, 2017 at 10:41 Comment(0)
M
7

Code sample below

pipeline {
    agent any
    stages {
        stage('find upstream job') {
            steps {
                script {
                    def causes = currentBuild.rawBuild.getCauses()
                    for(cause in causes) {
                        if (cause.class.toString().contains("UpstreamCause")) {
                            println "This job was caused by job " + cause.upstreamProject
                        } else {
                            println "Root cause : " + cause.toString()
                        }
                    }
                }      
            }
        }
    }
}

You can check the job's REST API to get extra information like below

{
  "_class" : "org.jenkinsci.plugins.workflow.job.WorkflowRun",
  "actions" : [
    {
      "_class" : "hudson.model.ParametersAction",
      "parameters" : [

      ]
    },
    {
      "_class" : "hudson.model.CauseAction",
      "causes" : [
        {
          "_class" : "hudson.model.Cause$UpstreamCause",
          "shortDescription" : "Started by upstream project \"larrycai-sto-46908390\" build number 7",
          "upstreamBuild" : 7,
          "upstreamProject" : "larrycai-sto-46908390",
          "upstreamUrl" : "job/larrycai-sto-46908390/"
        }
      ]
    },

Reference:

Muster answered 25/10, 2017 at 18:55 Comment(1)
See my update if it doesn't work for youGeoffreygeoffry
F
2

I realize that this is a couple years old, but the previous response required some additional security setup in my Jenkins instance. After a bit of research, I found that there was a new feature request completed in 11/2018 that addresses this need and exposes build causes in currentBuild. Here is a little lib I wrote that returns the cause with the string "JOB/" prepended if the build was triggered by another build:

def call(body) {
    if (body == null) {body = {DEBUG = false}}
    def myParams= [:]
    body.resolveStrategy = Closure.DELEGATE_FIRST
    body.delegate = myParams
    body()

    def causes = currentBuild.getBuildCauses()
    if (myParams.DEBUG) { 
        echo "causes count: " + causes.size().toString()
        echo "causes text : " + causes.toString()
    }
    for(cause in causes) {
        // echo cause
        if (cause._class.toString().contains("UpstreamCause")) {
            return "JOB/" + cause.upstreamProject
        } else {
            return cause.toString()
        }
    }
}

To use this, I place it in a library in a file named "buildCause.groovy". Then I reference the library at the top of my Jenkinsfile:

library identifier: 'lib@master', retriever: modernSCM(
        [$class: 'GitSCMSource', remote: '<LIBRARY_REPO_URL>',
         credentialsId: '<LIBRARY_REPO_CRED_ID', includes: '*'])

Then I can call it as needed within my pipeline:

def cause=buildCause()
echo cause
if (!cause.contains('JOB/')) {
    echo "started by user"
} else {
    echo "triggered by job"
}
Franctireur answered 16/5, 2019 at 23:54 Comment(1)
The feature request that added this functionality can be seen here: issues.jenkins-ci.org/browse/JENKINS-54227Franctireur
G
1

Larry's answer didn't quite work for me.

But, after I've modified it slightly with the help of these docs and this version works:

def causes = currentBuild.getBuildCauses()
for(cause in causes) {
    if (cause._class.toString().contains("UpstreamCause")) {
        println "This job was caused by job " + cause.upstreamProject
    } else {
        println "Root cause : " + cause.toString()
    }
}

P.S. Actually, Daniel's answer mentions this method, but there's too much clutter, I only noticed it after I wrote my solution.

Geoffreygeoffry answered 12/1, 2021 at 4:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.