詹金斯(Jenkins):在全局函数的主体中获取环境变量

时间:2018-08-27 16:22:51

标签: jenkins groovy jenkins-plugins jenkins-pipeline

我在PublishGitHub上有一个共享的全局函数。groovy看起来像这样:

#!/usr/bin/env groovy
def call(body)
{
    def config = [:]
    body.resolveStrategy = Closure.DELEGATE_FIRST
    body.delegate = config

    echo "\u001B[32mINFO: Publishing...\u001B[m"
    body()
    echo "\u001B[32mINFO: End Publish...\u001B[m"      
}

以及我的JenkinsFile上的代码:

environment {
    VERSION = "v1.3.${env.BUILD_NUMBER}"
}
stages {
    stage ('Publish WebAPI'){
        steps{
            echo "\u001B[32mINFO: Start Publish...\u001B[m"

            PublishGitHub{
                echo "This is a body with version: ${env.VERSION}"
            }               
        }
    }
}

这是我的输出:

[Pipeline] echo
INFO: Start Publish...
[Pipeline] echo
INFO: Publishing...
[Pipeline] }

并遵循下一个错误:

  

java.lang.NullPointerException:无法在null上获取属性“ VERSION”   对象

因为我体内没有环境变量?

3 个答案:

答案 0 :(得分:3)

您的共享库代码在工作流CPS上下文之外运行,因此,您传递给vars脚本的闭包无法识别env属性。您可以通过传递对工作流脚本的引用来解决此问题。如果您这样调用函数

PublishGitHub(this) {
    echo "This is a body with version: ${env.VERSION}"
}

然后您对vars/PublishGitHub.groovy脚本进行了小的修改,例如:

#!/usr/bin/env groovy

def call(config, body) {
    body.resolveStrategy = Closure.DELEGATE_FIRST
    body.delegate = config

    echo "\u001B[32mINFO: Publishing...\u001B[m"
    body()
    echo "\u001B[32mINFO: End Publish...\u001B[m"
}

那么您将成功运行管道:

[Pipeline] {
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Publish WebAPI)
[Pipeline] echo
[32mINFO: Start Publish...[m
[Pipeline] echo
[32mINFO: Publishing...[m
[Pipeline] echo
This is a body with version: v1.3.537
[Pipeline] echo
[32mINFO: End Publish...[m
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

如果您想限制共享库的范围,则始终可以简单地通过env而不是this并将vars/PublishGitHub.groovy更改为以下内容:

#!/usr/bin/env groovy

def call(env, body) {
    def config = [
            env: env
    ]
    body.resolveStrategy = Closure.DELEGATE_FIRST
    body.delegate = config

    echo "\u001B[32mINFO: Publishing...\u001B[m"
    body()
    echo "\u001B[32mINFO: End Publish...\u001B[m"
}

在这种情况下,您授予共享库仅对环境变量的访问权限。

答案 1 :(得分:0)

为了使您在Jenkinsfile中定义的环境变量在共享库代码中可用,您必须在对共享库方法的调用中传递 this 参数。

例如(下面是完整管道文件的部分提取):

// JENKINS-42730
@Library('pipeline-shared-library')_
import org.blah.MySharedLibraryClass
// END JENKINS_42730

pipeline {
     agent { any }

     environment {
         FOO = (new MySharedLibraryClass(config, this)).myMethod("StringVar1", "StringVar2")

     }
}

我的共享库:

package org.blah

import groovy.text.SimpleTemplateEngine

public class MySharedLibraryClass implements Serializable {
    def engine = new SimpleTemplateEngine()
    def config
    def steps

    def ArtifactoryHelper(config, steps) {
        this.config = config
        this.steps = steps
    }

    def log(msg){
        //Allows me to print to Jenkins console
        steps.println(msg)
    }

    def myMethod(var1, var2) {
        ....
    }

我上面提到的此参数映射到共享库代码中的步骤。然后,您应该能够在共享库代码中解析"VERSION=${steps.env.VERSION}"

也请参见此post

注意:

  1. pipeline-shared-library是我在Manage Jenkins>配置系统中赋予库的ID

答案 2 :(得分:0)

希蒙的答案有效。我添加了“ p.env = env”

def toParam(final Closure body) {
  final def p = [:]
  p.env = env
  body.resolveStrategy = Closure.DELEGATE_FIRST
  body.delegate = p
  body()
  return p
}