34

I am using the Pipeline plugin in Jenkins by Clouldbees (the name was Workflow plugin before), I am trying to get the user name in the Groovy script but I am not able to achieve it.

stage 'checkout svn'

node('master') {
      // Get the user name logged in Jenkins
}
Daniel Hernández
  • 4,078
  • 6
  • 27
  • 38
  • By *user name logged in Jenkins*, do you mean the user logged into the front-end? I.E. the one that manually (or automatically) triggers the job? Or the one actually running the job in the execution environment? Since you only distinguish this in the gray-on-gray-part of the question, the question would benefit from distinguishing this more clearly. – Rick Moritz Apr 16 '19 at 09:13
  • @RickMoritz you already pointed out what I meant, anyways I updated the question. – Daniel Hernández Apr 16 '19 at 13:38

12 Answers12

60

Did you try installing the Build User Vars plugin? If so, you should be able to run

node {
  wrap([$class: 'BuildUser']) {
    def user = env.BUILD_USER_ID
  }
}

or similar.

Jesse Glick
  • 24,539
  • 10
  • 90
  • 112
  • 3
    Thanks :) works great I didn't know about that plugin, checking the release notes I found that was the last update, support with workflow plugin ! great – Daniel Hernández Mar 09 '16 at 21:54
  • 2
    I'm trying this with a pipeline job. The wiki describes there should be a `Set jenkins user build variables` checkmark, but that seems only to be available in `Freestyle project`s. Is there anything else I'm missing? – dothebart Nov 30 '16 at 14:03
  • 1
    The checkbox is only for Freestyle jobs. But for Pipeline jobs, here's how to find out what's available. Scroll to `wrap: General Build Wrapper` in either the `Snippet Generator` checkbox, or https://your-jenkins.example.com/workflow-cps-snippetizer/dslReference page. – MarkHu Jan 25 '17 at 23:40
  • This is a dead link. Do you have another one for a sample? – Eddie May 30 '17 at 18:09
  • 3
    Please note that this plugin is listed as: `user build vars plugin` – dothebart Jan 30 '18 at 16:47
  • you are freaking awesome – Bernardo Vale Jun 01 '18 at 18:26
21

To make it work with Jenkins Pipeline:

Install user build vars plugin

Then run the following:

pipeline {
  agent any

  stages {
    stage('build user') {
      steps {
        wrap([$class: 'BuildUser']) {
          sh 'echo "${BUILD_USER}"'
        }
      }
    }
  }
}
Frak
  • 832
  • 1
  • 11
  • 32
YourAboutMeIsBlank
  • 1,787
  • 3
  • 18
  • 27
21

Here's a slightly shorter version that doesn't require the use of environment variables:

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

The use of rawBuild requires that it be in a @NonCPS block.

Mark Vardy
  • 311
  • 2
  • 4
  • Just FYSA: This solution or similar solutions won't work if a user clicks on "`Scan Multibranch Pipeline Now`" side bar link for Multi-Branch scan based initiated build. It only works if a user manually clicks on "Build" or "Build with Parameters" – AKS Apr 28 '21 at 19:20
  • https://stackoverflow.com/questions/67304608/jenkinsfile-jenkins-build-user-getusername-nullpointerexception-cannot-invo has a better example for finding/setting a user if you want to set build description using BUILD_USER, when "Scan MultiBranch Pipeline Now" side-bar link in a MultiBranch Pipeline job – AKS Apr 28 '21 at 20:04
12

It is possible to do this without a plugin (assuming JOB_BASE_NAME and BUILD_ID are in the environment):

def job = Jenkins.getInstance().getItemByFullName(env.JOB_BASE_NAME, Job.class)
def build = job.getBuildByNumber(env.BUILD_ID as int)
def userId = build.getCause(Cause.UserIdCause).getUserId()

There is also a getUserName, which returns the full name of the user.

Daan Bakker
  • 6,122
  • 3
  • 24
  • 23
  • Caveat: A job containing this script can only be run by an admin on Jenkins 2 due to security reasons. You can approve the script in Script Approval menu, though. – jeebface May 07 '19 at 15:17
  • 1
    I'm getting this error when I try this: `org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use staticMethod jenkins.model.Jenkins getInstance` – Katie May 23 '19 at 00:16
  • JOB_BASE_NAME and BUILD_ID are available in my environment. I already approved all the script permission, but im getting this error when using the codes above... java.lang.NullPointerException: Cannot invoke method getBuildByNumber() on null object – bencampbell_14 Jan 13 '20 at 10:34
  • @bencampbell_14 - you are probably having a "null" value for "job". add a "?" after the "job" symbol name in the second line. (and maybe as well on the third line after "build".) – Alexander Stohr Nov 10 '20 at 15:21
  • https://stackoverflow.com/questions/67304608/jenkinsfile-jenkins-build-user-getusername-nullpointerexception-cannot-invo answer – AKS Apr 28 '21 at 20:05
  • java.lang.NullPointerException: Cannot invoke method getBuildByNumber() on null object – JRichardsz Nov 24 '22 at 17:42
8

This works for me without the Build User plugin:

// get first entry of JSONArray
def buildCause = currentBuild.getBuildCauses()[0]
def buildPrincipal = [type:"unknown", name:""]

if (buildCause._class ==~ /.+BranchEventCause/) {
  def branchCause = currentBuild.getRawBuild().getCause(jenkins.branch.BranchEventCause)
  buildPrincipal = [type:"branch",name:buildCause.shortDescription]

} else
if (buildCause._class ==~ /.+TimerTriggerCause/) {
  def timerCause = currentBuild.getRawBuild().getCause(hudson.triggers.TimerTrigger.TimerTriggerCause)
  buildPrincipal = [type:"timer", name:"Timer event"]

} else
if (buildCause._class ==~ /.+UserIdCause/) {
  def buildUserCause = currentBuild.getRawBuild().getCause(hudson.model.Cause.UserIdCause)
  buildPrincipal = [type:"user", name:buildCause.userId]

} else
// ... other causes
Juergen
  • 81
  • 1
  • 3
  • I like this one, because if you are trying to pick a user to notify, when it's a UserIdCause, you use that, but if it's a branch, use the GIT_COMMITTER. Who to notify for failures to a timer-driven failure is likely nobody, or devops... – Ajax Jun 23 '20 at 09:26
6
def jobUserId, jobUserName
//then somewhere
wrap([$class: 'BuildUser']) {
    jobUserId = "${BUILD_USER_ID}"
    jobUserName = "${BUILD_USER}"
}
//then
println("Started By: ${jobUserName}")

We were using this plugin : Build User Vars Plugin. More variables are available.

Anand Varkey Philips
  • 1,811
  • 26
  • 41
  • would you please give me more details how to implement it? I am new to Jenkins, thanks a lot in advance. – Z.Liu Jul 08 '20 at 13:03
  • can you tell me what exactly are you trying to implement?? I have stopped using jenkins since almost 1.5 years. Thats why. – Anand Varkey Philips Jul 08 '20 at 17:50
  • thanks a lot for your reply, I already implemented it. at first, I do not know how to use def jobUsername, because I want to use it in the shared library, then I use the function get the user and return the username. thanks again. – Z.Liu Jul 09 '20 at 00:19
2
//Below is a generic groovy function to get the XML metadata for a Jenkins build.
//curl the env.BUILD_URL/api/xml parse it with grep and return the string
//I did an or true on curl, but possibly there is a better way
//echo -e "some_string \c" will always return some_string without \n char     
//use the readFile() and return the string
def GetUserId(){
 sh """
 /usr/bin/curl -k -s -u \
 \$USERNAME:\$PASSWORD -o \
 /tmp/api.xml \
 \$BUILD_URL/api/xml || true 

 THE_USERID=`cat /tmp/api.xml | grep -oP '(?<=<userId>).*?(?=</userId>)'`
 echo -e "\$THE_USERID \\c" > /tmp/user_id.txt                               
 """
def some_userid = readFile("/tmp/user_id.txt")
some_userid
}
JRova
  • 21
  • 2
1

I modified @shawn derik response to get it to work in my pipeline:

    stage("preserve build user") {
            wrap([$class: 'BuildUser']) {
                GET_BUILD_USER = sh ( script: 'echo "${BUILD_USER}"', returnStdout: true).trim()
            }
        }

Then I can reference that variable later on by passing it or in the same scope as ${GET_BUILD_USER} . I installed the same plugin referenced.

cgseller
  • 3,875
  • 2
  • 19
  • 21
1

Edit: I re-read the question - the below only gets you the user running the build (which technically is often more interesting), not the one triggering the build in the frontend (be it REST-API or WebUI). If you have Jenkins impersonation enabled, then I believe the result should be equivalent, otherwise this will only get you the user who owns the jenkins agent on the build machine.

Original answer:

Another way would be to

sh 'export jenkins_user=$(whoami)'

Downside: Linux-dependent, difficult to port across multiple agents in a single build (but then, the auth context may be different on each slave)

Upside: No need to install plugins (which on shared/large Jenkins instances can be tricky)

Rick Moritz
  • 1,449
  • 12
  • 25
1

The following code is inspired by Juergen's solution but I added more possible trigger reason and display them in a formatted manner:

String getTriggerReason() {
  def buildCause = currentBuild.getBuildCauses()[0]
  if (buildCause._class ==~ /.+(BranchEventCause|BranchIndexingCause)/) {
    if (env.JOB_BASE_NAME == 'master') {
      return 'Triggered by master commit'
    } else {
      return "Triggered by ${buildCause.shortDescription}"
    }
  }
  if (buildCause._class ==~ /.+TimerTriggerCause/) {
    return 'Triggered by timer'
  }
  if (buildCause._class ==~ /.+BuildUpstreamCause/) {
    return "Triggered by build #${buildCause.upstreamBuild}"
  }
  if (buildCause._class ==~ /.+UserIdCause/) {
    def userName = buildCause.userName.replaceFirst(/\s?\(.*/, '')
    return "Triggered by user ${userName}"
  }
  return 'Unknown trigger'
}
Manu CJ
  • 2,629
  • 1
  • 18
  • 29
  • When offers a similar range of options: https://www.jenkins.io/doc/book/pipeline/syntax/#when – coz Apr 19 '23 at 10:03
0

The Build User Vars Plugin is useful when you are executing the stage on an agent.

The alternative is to use the current build clause (see https://code-maven.com/jenkins-get-current-user), which also works when your stage is set with agent none.

Ceddaerrix
  • 304
  • 1
  • 14
0

Here is an example of a generic function that returns build user for the build from which it is called, or for the build that triggered the current build:

def getBuildUser() {
    currentBuild.rawBuild.getCause(Cause.UserIdCause)?.getUserId() ?: currentBuild.rawBuild.getCause(Cause.UpstreamCause).getUpstreamCauses().get(0).getUserId()
}
sintasy
  • 627
  • 11
  • 24