24

Executing upstream job called "A". On success of A executing test cases which is downstream project "B". But while sending mail from B we have to incorporate upstream project details (upstream project name, build no) in mail. So we can easily map / corelate the test run with respective upstream job.

In downstream project dashboard below details are displaying.

Started by upstream project Dev_RM_3.0_CI_Test build number 10
originally caused by:

I checked in https://wiki.jenkins-ci.org/display/JENKINS/Building+a+software+project. but couldnt find anything to inherit in downstream.

Created sample job with below details to display the current job details.

echo $BUILD_NUMBER
echo $JOB_NAME
echo $BUILD_ID

But the output is

Building on master in workspace /var/lib/jenkins/workspace/env
[env] $ /bin/sh -xe /tmp/hudson970280339057643719.sh
+ echo 1
1
+ echo env
env
+ echo 1
1
Finished: SUCCESS
  1. Any help to inherit upstream details in downstream job?
  2. How to get current job details?
divakar.scm
  • 1,256
  • 5
  • 21
  • 32
  • Possible duplicate of [How to use the build cause in build name?](https://stackoverflow.com/questions/37590320/how-to-use-the-build-cause-in-build-name) – twasbrillig Jul 06 '17 at 15:56

6 Answers6

31

The message that you refer to your question "Started by upstream project "Chained/1-First" build number 34" for example, is available in the jenkins Cause.

Jenkins keeps the upstream build info in it's cause object. If your are using build DSL or Pipelines you may get it in groovy. Alternatively you can curl the job url and use jq to get the Cause

For example curl http://localhost:8080/job/Chained/job/2-Second/17/api/json

"_class": "org.jenkinsci.plugins.workflow.job.WorkflowRun",
"actions": [{
  "_class": "hudson.model.CauseAction",
  "causes": [{
    "_class": "hudson.model.Cause$UpstreamCause",
    "shortDescription": "Started by upstream project \"Chained/1-First\" build number 34",
    "upstreamBuild": 34,
    "upstreamProject": "Chained/1-First",
    "upstreamUrl": "job/Chained/job/1-First/"
  }]
}

Or from the pipeline for example:

node() {
    stage('downstream') {
        def upstream = currentBuild.rawBuild.getCause(hudson.model.Cause$UpstreamCause)
        echo upstream?.shortDescription
    }
}

You can get a bunch of information out of Cause, pending all the script approvals or a global shared step. You will get a null if a different cause triggers this build, eg commit, or user.

razboy
  • 978
  • 7
  • 15
  • 1
    how do you do that in pipeline? – yorammi Sep 06 '17 at 13:15
  • In pipeline you can get the cause from current build. You will need a bunch of approvals. Alternatively put it in the global shared libs, as those don't get put through the sandbox. Also this type of cause will not be set if another cause triggered the job. I'll add an update to my answer. – razboy Oct 24 '17 at 08:27
  • 1
    Also there are [pipeline examples](https://github.com/jenkinsci/pipeline-examples/tree/master/pipeline-examples/get-build-cause) showing you how to do this. And in general there are similar posts [how to get $CAUSE in workflow](https://stackoverflow.com/questions/33587927/how-to-get-cause-in-workflow). – razboy Oct 24 '17 at 08:58
  • 1
    I'm a little late to the party here, so wondering if anyone has any further input on the preferred way to do this in say a Jenkins multi-branch pipeline build such that you're not needing to break out of the sandbox to access the upstream cause? I am interested in this to facilitate a CI build where we have one build outputting artifacts used by another. That is, I want job a to produce something used by job b, start job b, and job b to retrieve that something from somewhere keyed by that prior job's info. Wondering if I'm doing it wrong and should have a control job driving everything. – Kyle Mar 14 '19 at 16:53
  • This is the best answer, as it bypasses all the plugin and sandbox limitations. Just use curl and get the file, use read file to read the file and then use json slurper to read json and get what you want. Like so ```import groovy.json.JsonSlurper echo "${BUILD_URL}" sh "curl ${BUILD_URL}/api/json -o my_file.json" fileContents = readFile 'my_file.json' return new JsonSlurper().parseText(fileContents) ``` – Mahesh Jul 15 '19 at 07:00
12

You can pass in the upstream variables via build parameters to the downstream job and then you can access them (in the downstream job) using things such as ${MyParameter1} and ${MyParameter2}.

You would need to:

  1. Add build parameters to the downstream job. For example, a string parameter named "ParentJobName".
  2. Add a post build "Trigger downstream parameterized builds on other projects" to the upstream job.
  3. Add something like "Current Build parameters" or "Predefined parameters" to the #2 and pass in whatever you need. For example: ParentJobName=${JOB_NAME}
  4. Access the parameters as you would other build variables. e.g. ${ParentJobName}

You should be able to pass in the basic stuff that way. Anything more complicated than that and you will probably be better off using a plugin like Copy Artifacts Plugin to copy files or using the Jenkins API in a system groovy step to get/modify the upstream build, etc.

Daniel Omoto
  • 2,431
  • 17
  • 15
2

You can simply use params.variableName in your downstream job to retrieve the parameters passed from your upstream parameter job. Your downstream job need not necessarily be a parameterized job.

MeowRude
  • 176
  • 1
  • 6
2

You may have to have certain plugins installed, but

def causes = currentBuild.getBuildCauses()

will return an ArrayList of objects that will most likely provide the necessary details, for example upstreamProject for the full project name and upstreamBuild for the build number. Then you can correlate results between up- and downstream builds easily.

Source: link to pipeline-examples in razboy's comment above

Raketenolli
  • 743
  • 8
  • 24
1

Extending @razboy answer: this is good way if Cause cannot be whitelisted in sandbox. I forgot about Jenkins API and used current build console to look for string about trigger cause. You can try to fetch data from API as @razboy or get current console and grep it if you need simple stuff. Jenkins API is more flexible for more complex logic. To get API help,append /api to your build url: <jenkins_url>/job/<buildUrl>/<buildNumber>/api

   def buildUrl = env.BUILD_URL
   sh "wget $buildUrl -O currentConsole.txt"
   statusCode = sh returnStatus: true,script: 'cat currentConsole.txt | grep -q "Started by upstream project"'
   boolean startedByUpstream= statusCode==0
jozefow
  • 626
  • 3
  • 14
1

MeowRude's answer helped me. To repcap it, in upstream job:

build job: 'mail-test', parameters: [[$class: 'StringParameterValue', name: 'VERSION_NUMBER', value: '1.0.0.0']]

And in downstream job:

echo "${params.VERSION_NUMBER}"
Simon
  • 175
  • 1
  • 4