How to get the BUILD_USER in Jenkins when job triggered by timer?

Viewed 112888

I wanted to show the user who triggered a Jenkins job in the post job email. This is possible by using the plugin Build User Vars Plugin and the env variable BUILD_USER. But this variable do not get initialized when the job is triggered by a scheduler.

How can we achieve this? I know we have a plugin called - EnvInject Plugin, and that can be used...

But I just want to know how we can use this and achieve the solution...

17 Answers

Build user vars plugin wasn't working for me so I did a quick-and-dirty hack:

BUILD_CAUSE_JSON=$(curl --silent ${BUILD_URL}/api/json | tr "{}" "\n" | grep "Started by")
BUILD_USER_ID=$(echo $BUILD_CAUSE_JSON | tr "," "\n" | grep "userId" | awk -F\" '{print $4}')
BUILD_USER_NAME=$(echo $BUILD_CAUSE_JSON | tr "," "\n" | grep "userName" | awk -F\" '{print $4}')

SIMPLE SOLUTIONS (NO PLUGINS) !!

METHOD 1: Via Shell

BUILD_TRIGGER_BY=$(curl -k --silent ${BUILD_URL}/api/xml | tr '<' '\n' | egrep '^userId>|^userName>' | sed 's/.*>//g' | sed -e '1s/$/ \//g' | tr '\n' ' ')
echo "BUILD_TRIGGER_BY: ${BUILD_TRIGGER_BY}"

METHOD 2: Via Groovy

node('master') {
BUILD_TRIGGER_BY = sh ( script: "BUILD_BY=\$(curl -k --silent ${BUILD_URL}/api/xml | tr '<' '\n' | egrep '^userId>|^userName>' | sed 's/.*>//g' | sed -e '1s/\$/ \\/ /g'); if [[ -z \${BUILD_BY} ]]; then BUILD_BY=\$(curl -k --silent ${BUILD_URL}/api/xml | tr '<' '\n' | grep '^shortDescription>' | sed 's/.*user //g;s/.*by //g'); fi; echo \${BUILD_BY}", returnStdout: true ).trim()
echo "BUILD_TRIGGER_BY: ${BUILD_TRIGGER_BY}"
}

METHOD 3: Via Groovy

BUILD_TRIGGER_BY = "${currentBuild.getBuildCauses()[0].shortDescription} / ${currentBuild.getBuildCauses()[0].userId}"
echo "BUILD_TRIGGER_BY: ${BUILD_TRIGGER_BY}"

OUTPUT:

Started by user Admin / user@example.com

Note: Output will be both User ID and User Name

Without Plugin ->

def cause = currentBuild.getBuildCauses('hudson.model.Cause$UserIdCause')
echo "userName: ${cause.userName}"

I found similar but really working on Jenkins 2.1.x and easy for my understanding way. And it works without any plugins.

if (currentBuild.getBuildCauses('hudson.model.Cause$UserIdCause')['userId']){
    // Will be run only if someone user triggers build
    // Because in other cases this contructions returns null
}

You can use in this construction any classes described here. They will be returns maps with usable values.

This gets the username who clicked "Build Now" in a Jenkins pipeline job.

@NonCPS
def getBuildUser() {
    return currentBuild.rawBuild.getCause(Cause.UserIdCause).getUserId()
}

I'm using a combination of the 'Execute Shell' and 'Env Inject' plugin as follows:

  1. Create an 'Execute Shell' build step that uses shell parameter substitution to write default the value and echo that value into a file. Example highlighted in screen shot below.
  2. Use the 'Env Inject' file to read that file as properties to set.

Jenkins build steps to default variables

I wanted to trigger build initiator info to one of my slack/flock group so I used following way to get build initiator email and name by writing in Declarative fashion .

I am just printing here, you can use to store in some environment variable or write in one file giving file path according to your own convenience..

pipeline {
environment {
    BRANCH_NAME = "${env.BRANCH_NAME}"
    }
agent any

stages{
        stage('Build-Initiator-Info'){
                sh 'echo $(git show -s --pretty=%ae)'
                sh 'echo $(git show -s --pretty=%an)'
        }
           }
}

Just to elaborate on Musaffir Lp's answer. The Conditional Build Step plugin now supports the Build Cause directly - it requires the Run Condition Plugin also.

If you wanted to detect when the build was started by a timer you can select a Run? value of Build Cause, with Build Cause of: TimerTrigger

enter image description here

This is a little simpler and more robust than using a regex. There are also other triggers you can detect, for example when the build was a result of Source Control Management commit, you can select: SCMTrigger.

This below is working for me.

Install "user build vars plugin"

Build Name  =   ${BUILD_NUMBER}_${TICKET}_${ENV,var="BUILD_USER_ID"}

enter image description here

I created a function that return the Triggered Job Name:

String getTriggeredJob(CURRENT_BUILD) {

  if (CURRENT_BUILD.upstreamBuilds.size() > 0) {

    TRIGGERED_JOB = CURRENT_BUILD.upstreamBuilds[0].projectName

    if (!TRIGGERED_JOB.isEmpty()) {
      return TRIGGERED_JOB
    }
  } 

  return "Self"
}

CURRENT_BUILD is env var currentBuild

How to return Username & UserId:

UserName: currentBuild.rawBuild.getCause(Cause.UserIdCause).getUserName()

UserId: currentBuild.rawBuild.getCause(Cause.UserIdCause).getUserId()

There is other way to get user_id, where you don't need to install anything.

BUILD_USER_ID = sh (
    script: 'id -u',
    returnStdout: true
).trim()
echo "bUILD USER: ${BUILD_USER_ID }"

For declarative pipeline syntax, here is a quick hack, base on @Kevin answer. For declarative pipeline you need to enclose them in a node, else you will get an error/ build failure

node {
    def BUILD_FULL = sh (
        script: 'curl --silent '+buildURL+' | tr "{}" "\\n" | grep -Po \'"shortDescription":.*?[^\\\\]"\' | cut -d ":" -f2',
        returnStdout: true
        )

    slackSend channel: '#ci-cd',
          color: '#000000',
          message: "The pipeline was ${BUILD_FULL}  ${GIT_COMMIT_MSG} "

}

The output will be slack notification sent to your slack channel with the git short description

Related