Создание переменной среды 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. Поэтому мне пришлось сделать небольшой обходной путь:
Запустите groovy скрипт, который создает файл свойств, в котором указана переменная окружения
def props = new File("properties.text") if (props.text == 'foo=bar') { props.text = 'foo=baz' } else { props.text = 'foo=bar' }
Используйте плагин 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.