How do I always get a user who triggered a job? - jenkins

I have a code which displays on Slack user's mail who triggered a build:
def startedBy = "${currentBuild.getBuildCauses()[0].userId}#mycompany.com"
def message = \nJob started by: ${startedBy}"
return message
which gives on Slack:
Job started by: john.doe#mycompany.com
However, when same build is triggered by another build, I get:
Job started by: null#mycompany.com
because triggering build does not include userId class in "causes":
[[_class:hudson.model.Cause$UpstreamCause,
shortDescription:Started by upstream project "Production/myjob-starter" build number 3,
upstreamBuild:3,
upstreamProject:Production/myjob-starter,
upstreamUrl:job/Productionmyjob-starter/]]
On the other side, in UI there is a phrase:
originally caused by:
Started by user John Doe
My question is - how do I always get userId, no matter if build is triggered by another build or directly by a user?
Preferably, I would like to get userId, however Started by user John Doe - shortDescription would also be valid.
==================
EDIT: The solution was to install build-user-vars plugin which globally identifies user who triggered a job. Therefore groovy script looks like this:
def startedBy = "${env.BUILD_USER_ID}#mycompany.com"
def message = \nJob started by: ${startedBy}"
return message
and it prints userId no matter of build was started directly or by another build (triggered by a user)

Related

Is it possible to send Fortify SSC results in a Jenkins pipeline email?

Has anyone been successful in sending results from the Jenkins Fortify plugin (fortify-plugin) to developers via email using the Email Extension plugin (email-ext-plugin)?
I'm looking to add the List of Fortify SSC Issues summary to the build summary email by manipulating the Email Extension default Groovy template:
https://github.com/jenkinsci/email-ext-plugin/blob/master/src/main/resources/hudson/plugins/emailext/templates/groovy-html.template
I've been trying to use the getAction method to get information from the Fortify results similar to how JUnit tests are reported, but the problem I'm finding is that the Fortify Assessment is returned at the Jenkins project level instead of at the job level, so the following is never successful:
<%
def buildStatsAction = null
def buildStatsFolders = null
try {
buildStatsAction = it.getAction("com.fortify.plugin.jenkins.TableAction.BuildStatistics")
buildStatsFolders = buildStatsAction.getFolders()
} catch(e) {
//buildStatsAction not exist in this build
}

YouTube reporting API reports are all blank

I have created set of YouTube reporting jobs for a YouTube channel. The jobs were created and run every day as scheduled. However when I go to download the jobs they are all blank.
This is how I authenticate with the API:
def authenticate_from_credentials(API_SERVICE_NAME, API_VERSION):
youtube_client_id = os.environ['youtube_client_id']
youtube_client_secret = os.environ['youtube_client_secret']
youtube_refresh_token = os.environ['youtube_refresh_token']
credentials = client.OAuth2Credentials(
access_token=None,
client_id=youtube_client_id,
client_secret=youtube_client_secret,
refresh_token=youtube_refresh_token,
token_expiry=None,
token_uri='https://oauth2.googleapis.com/token',
user_agent=None,
revoke_uri=None
)
youtube_reporting = build(API_SERVICE_NAME, API_VERSION, credentials=credentials)
return youtube_reporting
This is the method I have been using to create the jobs:
# Call the YouTube Reporting API's jobs.create method to create a job.
def create_reporting_job(youtube_reporting, report_type_id, name):
# Provide keyword arguments that have values as request parameters.
reporting_job = youtube_reporting.jobs().create(
body=dict(
reportTypeId=report_type_id,
name=name
),
).execute()
print ('Reporting job "%s" created for reporting type "%s" at "%s"'
% (reporting_job['name'], reporting_job['reportTypeId'],
reporting_job['createTime']))
I authenticate like this:
youtube_reporting=authenticate_from_credentials('youtubereporting','v1')
And I will create a job like this:
create_reporting_job(youtube_reporting,"channel_combined_a2","Channel Combined a2")
I am not sure what the problem is here. The channel does have content and subscribers so the reports shouldn't be empty. I think there could be an issue with credentials or perhaps the wrong channel is associated with the report since the developer's Google accounts are different than the content owners. But I checked the channels associated with the Oauth credentials I am using and it was the right channel.
Why might my reports be empty and how can I fix this?
I hit the same issue, the problem is that you need to wait several hours for the report to become generated on the backend, at which point re-querying for reports will show results.
There is a subtle mention about this delay on https://developers.google.com/youtube/reporting/v1/reports under Step 3:
The API response to the jobs.create method contains a Job resource,
which specifies the ID that uniquely identifies the job. You can
start retrieving the report within 48 hours of the time that the job
is created, and the first available report will be for the day that
you scheduled the job.
This was quite confusing.

Retrieve jenkins job builder credentials in groovy

I am trying to extract the username and password in jenkins groovy script who has initiated the build. I need these details to post comments on jira from my name.
So for eg.. I login into jenkins and start a job, then my login credentials should be used to post the comment on jira..
I tried alot of posts but didnt find anytihng related to my requirement.
Any help will be appreciated..
after few seconds of Googling, I found this script officially published by cloudbees.
So, as follows:
Jenkins.instance.getAllItems(Job).each{
def jobBuilds=it.getBuilds()
//for each of such jobs we can get all the builds (or you can limit the number at your convenience)
jobBuilds.each { build ->
def runningSince = groovy.time.TimeCategory.minus( new Date(), build.getTime() )
def currentStatus = build.buildStatusSummary.message
def cause = build.getCauses()[0] //we keep the first cause
//This is a simple case where we want to get information on the cause if the build was
//triggered by an user
def user = cause instanceof Cause.UserIdCause? cause.getUserId():""
//This is an easy way to show the information on screen but can be changed at convenience
println "Build: ${build} | Since: ${runningSince} | Status: ${currentStatus} | Cause: ${cause} | User: ${user}"
// You can get all the information available for build parameters.
def parameters = build.getAction(ParametersAction)?.parameters
parameters.each {
println "Type: ${it.class} Name: ${it.name}, Value: ${it.dump()}"
}
}
}
You will get the user ID of the user, which start the job, for sure you will not be able to get his credentials, at least not in the plain text.
Little explanation
//to get all jobs
Jenkins.instance.getAllItems(Job)
{...}
//get builds per job
def jobBuilds=it.getBuilds()
//get build cause
def cause = build.getCauses()[0] //we keep the first cause
//if triggered by an user get id, otherwise empty string
def user = cause instanceof Cause.UserIdCause? cause.getUserId():""

Jenkins get user who aborted a build

Is there a way to get the username when a build is aborted by a user?
Preferably using jenkins pipeline code.
When a build is aborted by a user, it logs:
Aborted by <username>
so I hope it is stored as a variable for a brief period.
Use case: username to be later used to inform the user itself or other users via email or other means of messaging.
It seems that a InterruptedBuildAction object is inserted in to the list of build action if a job is aborted. This object can be used to retrieve the user that aborted the build. I use the following function in my Jenkinsfile:
#NonCPS
def getAbortUser()
{
def causee = ''
def actions = currentBuild.getRawBuild().getActions(jenkins.model.InterruptedBuildAction)
for (action in actions) {
def causes = action.getCauses()
// on cancellation, report who cancelled the build
for (cause in causes) {
causee = cause.getUser().getDisplayName()
cause = null
}
causes = null
action = null
}
actions = null
return causee
}
In fact you can have this information with the REST API, just use the following URL with an appropriate build:
/api/json?tree=actions[causes[*]]&pretty=true
And you should be able to find the requested information under actions[causes], e.g.:
{
"_class" : "jenkins.model.InterruptedBuildAction",
"causes" : [
{
"_class" : "jenkins.model.CauseOfInterruption$UserInterruption",
"shortDescription" : "Aborted by some_user_name"
}
]
},
Unfortunately there seem to be no other solutions at the moment but to tweak Jenkin's code itself and a workaround.
Post-Build actions → Editable Email Notification → Triggers → Add Trigger → Aborted → Send To → Add → Requestor → → ... Jenkins Mailer Plugin:
Sends email to the user who initiated the build.
There's no Aborter to add.
http://<jenkins>/job/<project name>/lastBuild/api/xml shows:
...
<result>ABORTED</result>
...
but there's no info who aborted the build either.
A workaround could be to curl http://<jenkins>/job/<project name>/<build #> in a Post build task script and to grep for <p>Aborted by user username</p>.

How to get culprits or committers inside a Jenkins workflow with one or more SCMs

Is it possible to access information about committers and/or culprits of a Jenkins workflow job when checking out from one or more SCMs (either via checkout() or other SCM steps like git/svn)?
The intention is to use that information to notify committers and/or culprits about the job status, for example in a mail step.
A small example of a workflow definition:
node {
// checkout from one or more SCMs, e.g.
git url: '<URL>'
checkout([$class:...])
...
// how can we know about committers or culprits at this point?
$committers = ??
// send a mail to committers or culprits
mail to: '$committers', subject: 'JENKINS', body: '<information about the job status>'
}
How could this be adapted to get a collection of the committers after running the SCM steps?
Edit:
I am currently working with Jenkins version 1.596.2 and Workflow: Aggregator version 1.6 and it seems this is an open issue in JENKINS-24141
This is now possible using the email-ext plugin.
def to = emailextrecipients([[$class: 'CulpritsRecipientProvider'],
[$class: 'DevelopersRecipientProvider'],
[$class: 'RequesterRecipientProvider']])
if (to != null && !to.isEmpty()) {
mail to: to, subject: "JENKINS", body: "See ${env.BUILD_URL}"
}
However, if you just want to send an email on failures, you may want to use Mailer (based on the email-ext pipeline examples):
step([$class: 'Mailer',
notifyEveryUnstableBuild: true,
recipients: emailextrecipients([[$class: 'CulpritsRecipientProvider'],
[$class: 'RequesterRecipientProvider']])])
Using groovy within a pipeline script:
#NonCPS // Necessary to allow .each to work.
def changelist() {
def changes = ""
currentBuild.changeSets.each { set ->
set.each { entry ->
changes += "${entry.commitId} by ${entry.author.fullName}\n"
}
}
changes
}
similar to the answer from #szym, but without the #NonCPS required:
def authors = currentBuild.changeSets.collectMany { it.toList().collect { it.author } }.unique()
As you found, pending JENKINS-24141 this is not supported. Changes to Jenkins core are required.
You can get the xml info for a job in which you will find the name of the person who committed the change along with the commit messages.
http://<Jenkins URL>:<Port Number>/job/<Jobname>/<BuildNumber>/api/xml?
Give this a go in your browser. Search for "user".
You can dump this information in a text file to process.
It seems that this feature was implemented inside the email-ext plugin but the author forgot to document the way we are supposed to use this.
Please check https://issues.jenkins-ci.org/browse/JENKINS-34763 -- and add a comment there, asking for an example. I already did.
You can fetch committers email :
committerEmail = sh (
script: 'git --no-pager show -s --format=\'%ae\'',
returnStdout: true
).trim()
and send:
emailext body: 'text you choose', subject: 'subject you choose', recipientProviders: [[$class: 'DevelopersRecipientProvider']], to: committerEmail
taken from : https://medium.com/#dilunika/find-the-git-commit-user-jenkins-pipeline-b6790613f8b5
In the emailext plugin you can provide culprits, developers, requestor etc in the recipientProviders directly.
emailext body: '',
recipientProviders: [culprits(),
developers(),
brokenBuildSuspects(),
brokenTestsSuspects(),
requestor()],
subject: ''
Description
Culprits: Sends email to the list of users who committed a change since the last non-broken build till now. This list at least always include people who made changes in this build, but if the previous build was a failure it also includes the culprit list from there.
Developers: Sends email to all the people who caused a change in the change set.
Broken Build suspects: Sends email to the list of users suspected of causing the build to begin failing.
Broken Test suspects: Sends email to the list of users suspected of causing a unit test to begin failing. This list includes committers and requestors of the build where the test began to fail, and those for any consecutive failed builds prior to the build in which the test began to fail.
Source: Jenkins Pipeline Syntax - Snippet Generator
If you want to notify the culprits who broke the build, You do not need to any checks, Use email plugin in jenkins. This plugin gives you option to send mails to commiter between past good build and current broken build.
If you are using "Editable email notifier plugin" You get option of send mail to culprit.
If you are using email plugin then you get the option "Send separate e-mails to individuals who broke the build".

Resources