简体   繁体   English

使用 Groovy 创建 Jenkins 环境变量

[英]Creating a Jenkins environment variable using Groovy

My project takes in a version number (separated by '.' or '_').我的项目采用版本号(以“.”或“_”分隔)。 I tried writing a Groovy script that creates a Jenkins environment variable using only the first two of these numbers:我尝试编写一个 Groovy 脚本,该脚本仅使用这些数字中的前两个来创建 Jenkins 环境变量:

//Get the version parameter
def env = System.getenv()
def version = env['currentversion']
def m = version =~/\d{1,2}/
env = ['miniVersion':m[0].m[1]]

Am I doing this correctly?我这样做正确吗? Can I even create a new environment variable?我什至可以创建一个新的环境变量吗? Is there a better solution to this?有没有更好的解决方案?

Jenkins 1.x詹金斯 1.x

The following groovy snippet should pass the version (as you've already supplied), and store it in the job's variables as 'miniVersion'.以下 groovy 代码段应该传递版本(正如您已经提供的那样),并将其作为“miniVersion”存储在作业的变量中。

import hudson.model.*

def env = System.getenv()
def version = env['currentversion']
def m = version =~/\d{1,2}/
def minVerVal = m[0]+"."+m[1]

def pa = new ParametersAction([
  new StringParameterValue("miniVersion", minVerVal)
])

// add variable to current job
Thread.currentThread().executable.addAction(pa)

The variable will then be accessible from other build steps.然后可以从其他构建步骤访问该变量。 eg例如

echo miniVersion=%miniVersion%

Outputs:输出:

miniVersion=12.34

I believe you'll need to use the "System Groovy Script" (on the Master node only) as opposed to the "Groovy Plugin" - https://wiki.jenkins-ci.org/display/JENKINS/Groovy+plugin#Groovyplugin-GroovyScriptvsSystemGroovyScript我相信您需要使用“系统 Groovy 脚本”(仅在主节点上)而不是“Groovy 插件” - https://wiki.jenkins-ci.org/display/JENKINS/Groovy+plugin# Groovyplugin-GroovyScriptvsSystemGroovyScript

Jenkins 2.x詹金斯 2.x

I believe the previous ( Jenkins 1.x ) behaviour stopped working because of this Security Advisory ...我相信之前( Jenkins 1.x )的行为因为这个安全公告而停止工作......

Solution (paraphrased from the Security Advisory)解决方案(从安全公告中转述)

It's possible to restore the previous behaviour by setting the system property hudson.model.ParametersAction.keepUndefinedParameters to true .可以通过将系统属性hudson.model.ParametersAction.keepUndefinedParameters设置为true来恢复以前的行为。 This is potentially very unsafe and intended as a short-term workaround only.这可能非常不安全,仅用作短期解决方法。

java -Dhudson.model.ParametersAction.keepUndefinedParameters=true -jar jenkins.war

To allow specific, known safe parameter names to be passed to builds, set the system property hudson.model.ParametersAction.safeParameters to a comma-separated list of safe parameter names.要允许将特定的已知安全参数名称传递给构建,请将系统属性hudson.model.ParametersAction.safeParameters设置为以逗号分隔的安全参数名称列表。

eg例如

java -Dhudson.model.ParametersAction.safeParameters=miniVersion,FOO,BAR -jar jenkins.war

You can also define a variable without the EnvInject Plugin within your Groovy System Script:您还可以在 Groovy 系统脚本中定义一个没有 EnvInject 插件的变量:

import hudson.model.*
def build = Thread.currentThread().executable
def pa = new ParametersAction([
  new StringParameterValue("FOO", "BAR")
])
build.addAction(pa)

Then you can access this variable in the next build step which (for example) is an windows batch command:然后你可以在下一个构建步骤中访问这个变量(例如)是一个 Windows 批处理命令:

@echo off
Setlocal EnableDelayedExpansion
echo FOO=!FOO!

This echo will show you "FOO=BAR".此回声将显示“FOO=BAR”。

Regards问候

For me, the following also worked in Jenkins 2 (2.73.3)对我来说,以下内容也适用于 Jenkins 2 (2.73.3)

Replace代替

def pa = new ParametersAction([new StringParameterValue("FOO", foo)])
build.addAction(pa)

with

def pa = new ParametersAction([new StringParameterValue("FOO", foo)], ["FOO"])
build.addAction(pa)

ParametersAction seems to have a second constructor which allows to pass in "additionalSafeParameters" https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/model/ParametersAction.java ParametersAction 似乎有第二个构造函数,它允许传入“additionalSafeParameters” https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/model/ParametersAction.java

As other answers state setting new ParametersAction is the way to inject one or more environment variables, but when a job is already parameterised adding new action won't take effect.正如其他答案所述,设置新的ParametersAction是注入一个或多个环境变量的方法,但是当作业已经参数化时,添加新操作将不会生效。 Instead you'll see two links to a build parameters pointing to the same set of parameters and the one you wanted to add will be null .相反,您将看到指向同一组参数的构建参数的两个链接,您想要添加的链接将为null

Here is a snippet updating the parameters list in both cases (a parametrised and non-parametrised job):这是在两种情况下更新参数列表的片段(参数化和非参数化作业):

import hudson.model.*

def build = Thread.currentThread().executable

def env = System.getenv()
def version = env['currentversion']
def m = version =~/\d{1,2}/
def minVerVal = m[0]+"."+m[1]

def newParams = null

def pl = new ArrayList<StringParameterValue>()
pl.add(new StringParameterValue('miniVersion', miniVerVal))

def oldParams = build.getAction(ParametersAction.class)

if(oldParams != null) {
  newParams = oldParams.createUpdated(pl)
  build.actions.remove(oldParams)
} else {
  newParams = new ParametersAction(pl)
}

build.addAction(newParams)

The Jenkins EnvInject Plugin might be able to help you. Jenkins EnvInject 插件或许可以帮到你。 It allows injecting environment variables into the build environment.它允许将环境变量注入构建环境。

I know it has some ability to do scripting, so it might be able to do what you want.我知道它有一些编写脚本的能力,所以它可能能够做你想做的事。 I have only used it to set simple properties (eg "LOG_PATH=${WORKSPACE}\\logs").我只用它来设置简单的属性(例如“LOG_PATH=${WORKSPACE}\\logs”)。

After searching around a bit, the best solution in my opinion makes use of hudson.model.EnvironmentContributingAction.经过一番搜索,我认为最好的解决方案是使用 hudson.model.EnvironmentContributingAction。

import hudson.model.EnvironmentContributingAction
import hudson.model.AbstractBuild 
import hudson.EnvVars

class BuildVariableInjector {

    def build
    def out

    def BuildVariableInjector(build, out) {
        this.build = build
        this.out = out
    }

    def addBuildEnvironmentVariable(key, value) {
        def action = new VariableInjectionAction(key, value)
        build.addAction(action)
        //Must call this for action to be added
        build.getEnvironment()
    }

    class VariableInjectionAction implements EnvironmentContributingAction {

        private String key
        private String value

        public VariableInjectionAction(String key, String value) {
            this.key = key
            this.value = value
        }

        public void buildEnvVars(AbstractBuild build, EnvVars envVars) {

            if (envVars != null && key != null && value != null) {
                envVars.put(key, value);
            }
        }

        public String getDisplayName() {
            return "VariableInjectionAction";
        }

        public String getIconFileName() {
            return null;
        }

        public String getUrlName() {
            return null;
        }
    }    
}

I use this class in a system groovy script (using the groovy plugin) within a job.我在作业中的系统 groovy 脚本(使用 groovy 插件)中使用此类。

import hudson.model.*
import java.io.File;
import jenkins.model.Jenkins;    

def jenkinsRootDir = build.getEnvVars()["JENKINS_HOME"];
def parent = getClass().getClassLoader()
def loader = new GroovyClassLoader(parent)

def buildVariableInjector = loader.parseClass(new File(jenkinsRootDir + "/userContent/GroovyScripts/BuildVariableInjector.groovy")).newInstance(build, getBinding().out)

def projectBranchDependencies = [] 
//Some logic to set projectBranchDependencies variable

buildVariableInjector.addBuildEnvironmentVariable("projectBranchDependencies", projectBranchDependencies.join(","));

You can then access the projectBranchDependencies variable at any other point in your build, in my case, from an ANT script.然后,您可以在构建中的任何其他点访问 projectBranchDependencies 变量,就我而言,是从 ANT 脚本访问。

Note: I borrowed / modified the ideas for parts of this implementation from a blog post, but at the time of this posting I was unable to locate the original source in order to give due credit.注意:我从一篇博客文章中借用/修改了此实现部分的想法,但在发布这篇文章时,我无法找到原始来源以给予应有的信任。

Just had the same issue.刚刚有同样的问题。 Wanted to dynamically trigger parametrized downstream jobs based on the outcome of some groovy scripting.想要根据一些 groovy 脚本的结果动态触发参数化的下游作业。

Unfortunately on our Jenkins it's not possible to run System Groovy scripts.不幸的是,在我们的 Jenkins 上无法运行 System Groovy 脚本。 Therefore I had to do a small workaround:因此我不得不做一个小的解决方法:

  1. Run groovy script which creates a properties file where the environment variable to be set is specified运行 groovy 脚本,该脚本创建一个属性文件,其中指定了要设置的环境变量

    def props = new File("properties.text") if (props.text == 'foo=bar') { props.text = 'foo=baz' } else { props.text = 'foo=bar' }
  2. Use env inject plugin to inject the variable written into this script使用 env inject 插件注入写入这个脚本的变量

    Inject environment variable Property file path: properties.text

After that I was able to use the variable 'foo' as parameter for the parametrized trigger plugin.之后,我可以使用变量“foo”作为参数化触发器插件的参数。 Some kind of workaround.某种解决方法。 But works!但是有效!

My environment was prior tooling such as Jenkins and was running with batch files (I know, I'm old).我的环境是以前的工具,例如 Jenkins,并且正在运行批处理文件(我知道,我老了)。 So those batch files (and their sub-batch files) are using environment variables.所以那些批处理文件(及其子批处理文件)正在使用环境变量。 This was my piece of groovy script which injects environment variables.这是我的一段 groovy 脚本,它注入了环境变量。 The names and parameters used are dummy ones.使用的名称和参数是虚拟的。

// The process/batch which uses environment variables
def buildLabel = "SomeVersionNr"
def script = "startBuild.bat"
def processBuilder = new ProcessBuilder(script, buildLabel)

//Inject our environment variables
Map<String, String> env = processBuilder.environment()
env.put("ProjectRoot", "someLocation")
env.put("SomeVar", "Some")

Process p = processBuilder.start()
p.waitFor()

Of course if you set Jenkins up from scratch you would probably do it differently and share the variables in another way, or pass parameters around but this might come handy.当然,如果您从头开始设置 Jenkins,您可能会采用不同的方式并以另一种方式共享变量,或者传递参数,但这可能会派上用场。

On my side it only worked this way by replacing an existing parameter.就我而言,它只能通过替换现有参数来以这种方式工作。

def artifactNameParam = new StringParameterValue('CopyProjectArtifactName', 'bla bla bla')
build.replaceAction(new ParametersAction(artifactNameParam))

Additionally this script must be run with system groovy .此外,此脚本必须与系统 groovy一起运行。

A groovy must be manually installed on that system and the bin dir of groovy must be added to path .必须在该系统上手动安装 groovy,并且必须将 groovy 的bin目录添加到path Additionally in the lib folder I had to add jenkins-core.jar .另外在lib文件夹中,我必须添加jenkins-core.jar

Then it was possible to modify a parameter in a groovy script and get the modified value in a batch script after to continue work.然后可以在 groovy 脚本中修改参数并在继续工作后在批处理脚本中获取修改后的值。

For me the following worked on Jenkins 2.190.1 and was much simpler than some of the other workarounds:对我来说,以下适用于 Jenkins 2.190.1 并且比其他一些解决方法简单得多:

matcher = manager.getLogMatcher('^.*Text we want comes next: (.*)$');

if (matcher.matches()) {
    def myVar = matcher.group(1);
    def envVar = new EnvVars([MY_ENV_VAR: myVar]);
    def newEnv = Environment.create(envVar);
    manager.build.environments.add(0, newEnv);
    // now the matched text from the LogMatcher is passed to an
    // env var we can access at $MY_ENV_VAR in post build steps
}

This was using the Groovy Script plugin with no additional changes to Jenkins.这是使用 Groovy Script 插件,对 Jenkins 没有额外更改。

You can also create a global environment variable for jenkins if want to use wider.如果要使用更广泛,您还可以为 jenkins 创建一个全局环境变量。 Written here longer.在这里比较长。

import hudson.EnvVars;
import hudson.slaves.EnvironmentVariablesNodeProperty;
import hudson.slaves.NodeProperty;
import hudson.slaves.NodePropertyDescriptor;
import hudson.util.DescribableList;
import jenkins.model.Jenkins;
public createGlobalEnvironmentVariables(String key, String value){

       Jenkins instance = Jenkins.getInstance();

       DescribableList<NodeProperty<?>, NodePropertyDescriptor> globalNodeProperties = instance.getGlobalNodeProperties();
       List<EnvironmentVariablesNodeProperty> envVarsNodePropertyList = globalNodeProperties.getAll(EnvironmentVariablesNodeProperty.class);

       EnvironmentVariablesNodeProperty newEnvVarsNodeProperty = null;
       EnvVars envVars = null;

       if ( envVarsNodePropertyList == null || envVarsNodePropertyList.size() == 0 ) {
           newEnvVarsNodeProperty = new hudson.slaves.EnvironmentVariablesNodeProperty();
           globalNodeProperties.add(newEnvVarsNodeProperty);
           envVars = newEnvVarsNodeProperty.getEnvVars();
       } else {
           envVars = envVarsNodePropertyList.get(0).getEnvVars();
       }
       envVars.put(key, value)
       instance.save()
}
createGlobalEnvironmentVariables('Var1','Dummy')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM