首页 > 解决方案 > Jenkinsfile - Jenkins 构建用户 getUserName() NullPointerException:无法在 null 对象上调用方法 getUserName() Mutli Branch Indexing Scanning

问题描述

Jenkins 2.138.1.2-rolling --and-- 使用MultiBranch Pipeline(从主、分支和拉取请求等构建构建)。

我想向 Jenkins 构建作业的用户展示在构建描述中发起构建的用户。

前任: 在此处输入图像描述

为了实现相同的功能,在我Jenkinsfile的顶部有以下代码:

@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 {
    ...
}

类定义:https ://javadoc.jenkins-ci.org/hudson/model/Cause.UserIdCause.html显示该方法未被弃用(就像在UserCause类的情况下一样)。

在 Jenkinsfile 的阶段部分下,我有以下代码,它成功地实现了这一点。

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 ..
 }

当我使用多分支管道作业时,我看到了所有分支/PR,包括 master,在侧边栏上,我看到了以下链接:

在此处输入图像描述

多分支扫描周期设置为每10分钟一次。 在此处输入图像描述

我看到有时构建失败并出现以下错误java.lang.NullPointerException: Cannot invoke method getUserName() on null object,有时,构建一直成功并且构建描述也很好。

[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

我注意到,仅Multi-Branch Scanning/在后台运行时才会发生这种情况Branch Indexing,因为所有失败的构建都在该构建号的控制台页面中列出了以下内容。 在此处输入图像描述

对于带有构建描述的成功构建和所有,上面的“ BRANCH INDEXING ”框是不可见的(针对成功的构建#)。

为什么我会收到此 java.lang.NullPointerException: Cannot invoke method getUserName() on null object错误(在后台进行扫描时)——或者我可以做些什么来避免构建失败

PS:要重新创建此问题,用户只需单击立即扫描多分支管道
的 侧边栏图标/链接,这将导致构建失败和控制台输出显示:

在此处输入图像描述

PS:安装一个新插件可能需要一些时间(1-2 周)/扫描/安全团队的批准过程,所以我认为这不是一个选项,至少在获得批准之前是这样。例如:https ://plugins.jenkins.io/build-user-vars-plugin/

标签: jenkinsnullpointerexceptionjenkins-pipelinejenkins-pluginsmultibranch-pipeline

解决方案


为避免构建失败,目前,我启用trycatch设置 BUILD_USER if getCause(...)is going to fail ...就像当有人点击侧边栏链接Scan MultiBranch Pipeline Now时,控制台输出或Jenkins没有设置点击那个的用户用于启动构建的侧边栏链接(如果要构建任何更改)并显示Branch Indexing为输出中的第一行(而不是显示:)Started by user <some name> (someUserID)

因此,以下将 BUILD_USER 设置为有意义的值,并且不会使构建失败。

@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
}

我仍然想知道是否有办法,我们可以找到,点击侧边栏链接(登录用户)的人会戳进去。


推荐阅读