Jenkinsfile - Jenkins build user getUserName() NullPointerException: Cannot invoke method getUserName() on null object Mutli Branch Indexing Scanning
Z

1

2

Jenkins 2.138.1.2-rolling --and-- using MultiBranch Pipeline (to build build from master, branches and Pull Requests etc).

I want to show Jenkins build job's user who initiated the build in build description.

Ex: enter image description here

For implemennting the same, in my Jenkinsfile, I have the following code at the top:

@NonCPS
def getBuildUser() {
    def build = currentBuild.rawBuild
    def cause = build.getCause(hudson.model.Cause.UserIdCause.class)
    def BUILD_USER = cause.getUserName()
    
    return BUILD_USER
}

pipeline {
    ...
}

Class definition: https://javadoc.jenkins-ci.org/hudson/model/Cause.UserIdCause.html shows the method is NOT Deprecated (like it's in the case of UserCause class).

In Jenkinsfile, under the stages section, I have the following code, which is implementing this successfully.

stages {
   stage ('Start') {
       steps {
           script {
                   // Set Build Description
                   def BUILD_USER= getBuildUser()
                   currentBuild.description = "${BUILD_USER}: ${RELEASE_TAG} => ${DOCKER_IMAGES}"
           }

           sh '''
                 set +x
                 echo -e "\n\n-- Starting build process.\n"
              '''
       }
   }
   .. more stages are here ..
 }

As I'm using Multi-Branch Pipeline job, I see all the branches/PR including master and on the side bar, I see the following links:

enter image description here

The setting for multi-branch scan period is set for every 10 minutes. enter image description here

I'm seeing that sometimes the build is FAILING with the following error i.e. java.lang.NullPointerException: Cannot invoke method getUserName() on null object and other times, the build is successful all the way and build description is also good.

[Bitbucket] Build result notified
java.lang.NullPointerException: Cannot invoke method getUserName() on null object
    at org.codehaus.groovy.runtime.NullObject.invokeMethod(NullObject.java:91)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:48)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.NullCallSite.call(NullCallSite.java:35)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
    at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:158)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:160)
    at org.kohsuke.groovy.sandbox.impl.Checker$checkedCall$1.callStatic(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:56)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:194)
    at WorkflowScript.getBuildUser(WorkflowScript:5)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1213)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:42)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
    at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:158)
    at org.kohsuke.groovy.sandbox.GroovyInterceptor.onMethodCall(GroovyInterceptor.java:23)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:157)
    at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:156)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:160)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:125)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:130)
    at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.methodCall(SandboxInvoker.java:17)
    at WorkflowScript.run(WorkflowScript:75)
    at ___cps.transform___(Native Method)
    at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:57)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:109)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixName(FunctionCallBlock.java:77)
    at sun.reflect.GeneratedMethodAccessor333.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
    at com.cloudbees.groovy.cps.impl.ConstantBlock.eval(ConstantBlock.java:21)
    at com.cloudbees.groovy.cps.Next.step(Next.java:83)
    at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:174)
    at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:163)
    at org.codehaus.groovy.runtime.GroovyCategorySupport$ThreadCategoryInfo.use(GroovyCategorySupport.java:122)
    at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:261)
    at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:163)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.access$001(SandboxContinuable.java:18)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:51)
    at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:174)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:347)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$200(CpsThreadGroup.java:93)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:259)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:247)
    at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:64)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:131)
    at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
    at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:59)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Finished: FAILURE

I noticed, that this is happening ONLY when Multi-Branch Scanning / Branch Indexing is running in the background because, as all the failed builds have the following getting listed in that build number's console page. enter image description here

For successful builds with build description and all, the above "BRANCH INDEXING" box is not visible (against that successful build #).

Why I'm getting this java.lang.NullPointerException: Cannot invoke method getUserName() on null object error (when Scanning is in progress in the background) --or what can I do to avoid the build failure?

PS: To recreate this issue, a user can simply just click on the
sidebar icon/link for Scan Multibranch Pipeline Now which will result in a failed build and console output showing:

enter image description here

PS: Installing a new plugin will probably require some time(1-2 weeks)/scanning/approval process from Security team, so not an option I think, at least until that approval happens. Ex: https://plugins.jenkins.io/build-user-vars-plugin/

Zoroastrian answered 28/4, 2021 at 16:55 Comment(0)
Z
1

To avoid build failure, for now, I enabled try and catch and setting value for BUILD_USER if getCause(...) is going to fail ... as when someone clicks on the side-bar link Scan MultiBranch Pipeline Now, then console output or Jenkins doesn't set a USER who clicked on that side-bar link to launch the build (if there are any changes to be built) and shows Branch Indexing as first line in output (instead of showing: Started by user <some name> (someUserID)).

Thus, the following will set BUILD_USER to a meaningful value and won't FAIL the build.

@NonCPS
def getBuildUser() {
        def build = currentBuild.rawBuild
        def BUILD_USER = "ToBeSet"

        try {
             def cause = build.getCause(hudson.model.Cause.UserIdCause.class)
             BUILD_USER = cause.getUserName()
        } catch(Exception ex) {
             println "\n\n-- Build caused by either Multi-Branch Pipeline Scanning -or- Timer i.e. not directly by a logged in user\n";
             BUILD_USER = "Multi_Branch_Scan_or_Timer"
        }

        return BUILD_USER
}

I'll still like to know if there's a way, we can find, who clicked on the side-bar link (logged in user), will poke into it.

Zoroastrian answered 28/4, 2021 at 19:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.