Создание переменной среды Jenkins с использованием 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]]

Я делаю это правильно, могу ли я даже создать новую переменную среды, и есть ли лучшее решение для этого.

11 ответов

Решение

Дженкинс 1.x

Следующий фрагмент кода должен передать версию (как вы уже предоставили) и сохранить ее в переменных задания как "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)

Переменная будет доступна с других шагов сборки. например

echo miniVersion=%miniVersion%

Выходы:

miniVersion=12.34

Я считаю, что вам нужно использовать "Системный скрипт Groovy" (только на главном узле), а не "Плагин Groovy" - https://wiki.jenkins-ci.org/display/JENKINS/Groovy+plugin

Дженкинс 2.x

Я считаю, что предыдущее поведение (Jenkins 1.x) перестало работать из-за этой рекомендации по безопасности...

Решение (перефразировано из Рекомендации по безопасности)

Можно восстановить предыдущее поведение, установив системное свойство hudson.model.ParametersAction.keepUndefinedParameters в true, Это потенциально очень небезопасно и предназначено только в качестве краткосрочного обходного пути.

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

Чтобы разрешить передачу определенных, известных безопасных имен параметров в сборки, установите системное свойство hudson.model.ParametersAction.safeParameters в разделенный запятыми список безопасных имен параметров.

например

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

Вы также можете определить переменную без плагина EnvInject в вашем системном скрипте Groovy:

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

Затем вы можете получить доступ к этой переменной на следующем этапе сборки, который (например) является пакетной командой Windows:

@echo off
Setlocal EnableDelayedExpansion
echo FOO=!FOO!

Это эхо покажет вам "FOO=BAR".

С уважением

Для меня следующее работало в Jenkins 2 (2.73.3)

замещать

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

с

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

У ParametersAction, похоже, есть второй конструктор, который позволяет передавать "AdditionalSafeParameters" https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/model/ParametersAction.java

Поскольку другие ответы заявляют установку, новую ParametersAction это способ ввести одну или несколько переменных среды, но когда задание уже параметризовано, добавление нового действия не вступит в силу. Вместо этого вы увидите две ссылки на параметры сборки, указывающие на один и тот же набор параметров, и тот, который вы хотите добавить, будет null,

Вот фрагмент обновления списка параметров в обоих случаях (параметризованное и непараметрическое задание):

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)

Плагин Jenkins EnvInject может вам помочь. Это позволяет вводить переменные среды в среду сборки.

Я знаю, что у него есть возможность создавать сценарии, поэтому он может делать то, что вы хотите. Я использовал его только для установки простых свойств (например, "LOG_PATH=${WORKSPACE}\logs").

После небольшого поиска лучшее решение, на мой взгляд, использует 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;
        }
    }    
}

Я использую этот класс в системном скрипте 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(","));

Затем вы можете получить доступ к переменной projectBranchDependencies в любой другой точке вашей сборки, в моем случае, из сценария ANT.

Примечание: я заимствовал / изменил идеи для частей этой реализации из поста в блоге, но на момент публикации я не смог найти первоначальный источник, чтобы отдать должное.

Просто была такая же проблема. Хотел динамически запускать параметризованные последующие задания, основываясь на результатах некоторых классных сценариев.

К сожалению, на наших Jenkins невозможно запускать скрипты System Groovy. Поэтому мне пришлось сделать небольшой обходной путь:

  1. Запустите groovy скрипт, который создает файл свойств, в котором указана переменная окружения

    def props = new File("properties.text")
    if (props.text == 'foo=bar') {
        props.text = 'foo=baz'
    } else {
        props.text = 'foo=bar'
    }
    
  2. Используйте плагин env inject для внедрения переменной, записанной в этот скрипт

    Inject environment variable
    Property file path: properties.text
    

После этого я смог использовать переменную 'foo' в качестве параметра для параметризованного триггерного плагина. Какой-то обходной путь. Но работает!

Моей средой был предыдущий инструментарий, такой как Jenkins, и он работал с пакетными файлами (я знаю, я стар). Таким образом, эти пакетные файлы (и их подпакетные файлы) используют переменные среды. Это был мой отличный скрипт, который вводит переменные окружения. Используемые имена и параметры являются фиктивными.

// 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()

Конечно, если вы настроите Jenkins с нуля, вы, вероятно, сделаете это по-другому и поделите переменные другим способом или передадите параметры, но это может пригодиться.

На моей стороне это сработало только путем замены существующего параметра.

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

Кроме того, этот сценарий должен запускаться с системным Groovy.

Groovy необходимо вручную установить в этой системе, а каталог bin файла groovy должен быть добавлен в path. Кроме того, в папке lib мне пришлось добавить jenkins-core.jar.

Затем можно было изменить параметр в отличном сценарии и получить измененное значение в пакетном сценарии, чтобы продолжить работу.

Вы также можете создать глобальную переменную среды для jenkins, если хотите использовать ее шире. Здесь написано дольше.

      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')

Для меня следующее работало над 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
}

При этом использовался плагин Groovy Script без дополнительных изменений в Jenkins.

Другие вопросы по тегам