Reputation: 1266
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
Upvotes: 25
Views: 70713
Reputation: 11916
In Jenkins' groovy pipeline, you can use currentBuild
(a RunWrapper) for build details and getUpstreamBuilds()
to get the same information about upstream builds. Unlike currentBuild.rawBuild.getCause()
, this doesn't appear to require any script approval.
Here's an example where we search for the username who started a build. I use this to send that user a slack message when their triggered build completes.
import org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper
// Usually, call this with currentBuild global:
// def username = userWhoTriggeredBuild(currentBuild)
// Returns null if the build wasn't triggered by a user (could be a hook)
// or their id wasn't an email address (bot user?).
def userWhoTriggeredBuild(RunWrapper build) {
def cause = build.getBuildCauses('hudson.model.Cause$UserIdCause')
def user_id_list = cause?.userId
if (user_id_list) {
for (email in user_id_list) {
echo "[userWhoTriggeredBuild] Found user_id '${email}' in build #${build.id}"
def parts = email.split("@")
if (parts.length > 0) {
return parts[0]
}
}
echo "[userWhoTriggeredBuild] Got user list, but no acceptable users in build #${build.id}"
return null
}
// Recursive case: walk through all upstream builds to find a user.
// Eventually, getUpstreamBuilds should return an empty list and we exit.
for (upstream in build.getUpstreamBuilds()) {
if (upstream == build) {
// I don't think this should be possible, but just in case.
continue
}
echo "[userWhoTriggeredBuild] Found upstream build '${upstream}' from build #${build.id}"
def user = userWhoTriggeredBuild(upstream)
if (user) {
return user
}
}
echo "[userWhoTriggeredBuild] Found no acceptable users in build #${build.id}"
return null
}
Once it's working, remove those [userWhoTriggeredBuild]
echo lines which are just to help you see what it's doing and how it's working.
Upvotes: 0
Reputation: 23
To retrieve all the upstreamJobs
, you can utilize the getUpstreamBuilds()
method from currentBuild
. This function returns all the UpstreamBuilds
except for the last one. See the Jenkins documentation: RunWrapper.getUpstreamBuilds().
https://stackoverflow.com/a/78663413/12241186
Upvotes: 0
Reputation: 745
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
Upvotes: 2
Reputation: 175
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}"
Upvotes: 1
Reputation: 176
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.
Upvotes: 2
Reputation: 1028
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.
Upvotes: 32
Reputation: 786
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
Upvotes: 1
Reputation: 2481
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:
ParentJobName=${JOB_NAME}
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.
Upvotes: 12