声明性Jenkinsfile中的动态变量导致NPE

时间:2017-10-19 14:57:31

标签: jenkins groovy jenkins-pipeline

在我的声明性Jenkinsfile中,我试图计算一些值,然后将它们传递给maven。虽然看起来很简单,但我无法使其发挥作用。

这是我的Jenkinsfile的相关部分:

def port = 1000 as Integer
def mocksport = 0 as Integer
def safebranch='unknown'

pipeline {
  stages {
    stage('Compile'){
        steps {
            script {
              safebranch=env.BRANCH_NAME.toLowerCase().replaceAll("[-_/]", "");
              for (int i=0; i<safebranch.length(); i++) {
                port = (port as Integer) + (Character.getNumericValue(safebranch.charAt(i)) as Integer);
              }
              port = (port as Integer) % 99 + 9000;
              mocksport = (port as Integer) + 1;
              echo "Application will be deployed on port ${port}"
              echo "Mocks will be deployed on port ${mocksport}"​​​​​​​​​​​​​
            }
            sh "mvn clean install -Dmaven.test.failure.ignore=true -T 1C -Drancher.port=${port} -Drancher.mocks.port=${mocksport} -Drancher.tag=${safebranch}​"
        }
      }
    } // stages
} // pipeline

这个版本是我能找到最接近工作解决方案的版本。至少执行脚本块并且回显的值是正确的:在日志中我看到:

[Pipeline] [Compile] echo
[Compile] Application will be deployed on port 9065
[Pipeline] [Compile] echo
[Compile] Mocks will be deployed on port 9066

我现在得到这个异常,可能与groovy无法在脚本块上下文之外找到变量有关:

java.lang.NullPointerException: Cannot get property '​​​​​​​​​​​​​' on null object
    at org.codehaus.groovy.runtime.NullObject.getProperty(NullObject.java:60)
    at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:174)
    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.java:456)
    at org.kohsuke.groovy.sandbox.impl.Checker$6.call(Checker.java:284)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:286)
    at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getProperty(SandboxInvoker.java:29)
    at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:20)

我尝试在管道下的全局环境部分声明变量,并使用“env”访问它们。前缀,但在这种情况下似乎不允许脚本块更新值(=我得到1000和0作为回声的结果)。

我该如何做到这一点?

奖金问题:奇怪的是,变量似乎总是以字符串形式处理。如果我没有在每个变量用法时将转换添加到Integer,它就不起作用(端口变量在每次迭代时扩展:1000,10001012,100010122343等...)。我可以声明并将变量用作整数吗?

1 个答案:

答案 0 :(得分:2)

我们在设置变量时没有看到变量的范围问题。它们应该在script{}块之外可用。错误消息也没有真正指向范围问题。

我接受了您粘贴的确切代码,添加了代理声明,并为&#34; safebranch&#34;制作了一个值。它完全按照我的预期运行(当然没有找到mvn命令)。

Running shell script
+ mvn clean install -Dmaven.test.failure.ignore=true -T 1C -Drancher.port=9011 -Drancher.mocks.port=9012 -Drancher.tag=BRANCH
/home/jenkins/jenkins/workspace/morepipe@tmp/durable-6849aecb/script.sh: 2: /home/jenkins/jenkins/workspace/morepipe@tmp/durable-6849aecb/script.sh: mvn: not found

我甚至摆脱了所有to Integer类型的强制,它运行正常。也许问题实际上是你没有发布的脚本的一部分。这是我的确切脚本。尝试插入它并查看它是否运行:

def port = 1000
def mocksport = 0
def safebranch='unknown'

pipeline {
  agent any
  stages {
    stage('Compile'){
        steps {
            script {
              safebranch="BRANCH"
              for (int i=0; i<safebranch.length(); i++) {
                port = (port) + (Character.getNumericValue(safebranch.charAt(i)));
              }
              port = (port) % 99 + 9000;
              mocksport = (port) + 1;
              echo "Application will be deployed on port ${port}"
              echo "Mocks will be deployed on port ${mocksport}"
            }
            sh "mvn clean install -Dmaven.test.failure.ignore=true -T 1C -Drancher.port=${port} -Drancher.mocks.port=${mocksport} -Drancher.tag=${safebranch}"
        }
      }
    } // stages
} // pipeline