#groovy #jenkins-pipeline #jenkins-declarative-pipeline
#groovy #дженкинс-конвейер #дженкинс-декларативный конвейер
Вопрос:
Я могу объявить экземпляр класса как глобальный следующим образом :
gitUtils = new GitUtils()
pipeline {
...
echo "hello: " gitUtils.doSomething()
}
Но если конвейер вызывает функцию, определенную как groovy script в каталоге «vars», gitUtils
она больше не отображается
def call() {
def something = gitUtils.doSomething()
}
Я также пытался использовать @Field, но это ничего не меняет. Обратите внимание, что весь конвейер определен в общей библиотеке (project jenkinsfile просто вызывает функцию из этой общей библиотеки).
Как получить доступ к gitUtils из groovy scripts в /vars в этом примере?
Я знаю, что мы могли бы передать экземпляр в качестве параметра функции, объявленной в /vars, но чем больше у вас функций, использующих ваш утилитарный класс, тем больше это уродливо. Не могли бы вы представить себе передачу функции ‘echo’ или ‘sh’ в качестве параметра? Нет, здесь то же самое.
Я знаю, что мы не могли использовать все классы, определенные в src, и определять groovy script с несколькими общедоступными методами. Здесь мы могли бы представить, что создаем в /vars файл gitutils.groovy со многими общедоступными методами. Но это означало бы использовать закрытие ‘script’ в конвейере, чтобы выбрать, какой метод мы хотим, например:
script {
gitutils.doSomething()
}
Я этого не хочу. Я бы предпочел создать одну функцию для каждого groovy script в /vars . Таким образом, мы можем вызывать их непосредственно поэтапно, вот так:
steps {
myGroovyScriptFunction()
}
Но, делая это, количество функций увеличивается, а функции организованы неправильно. Вот почему идея состоит в том, чтобы создать «функцию большого шага» в /vars, которая использует внутри более универсальные функции, из экземпляров классов (даже статических в лучшем случае). Итак, вместо создания нового экземпляра в каждом groovy script мне нужен глобальный экземпляр.
Контекст: декларативный конвейер, openshift jenkins, подчиненный с динамическим шаблоном pod
Ответ №1:
Это невозможно из-за JENKINS-42360.
На мой взгляд, лучший способ использовать глобальные шаги без блока сценария — это определить экземпляр GitUtils
и использовать его непосредственно в глобальных шагах. Если вам нужен контекст шага конвейера, вы можете передать его конструктору:
# vars/myStep.groovy
import my.packagename.GitUtils
def call() {
GitUtils gitUtils = new GitUtils(steps)
...
}
затем вы можете использовать шаги с inside GitUtils
, как описано здесь . Не забудьте определить GitUtils
для реализации Serializable
в соответствии с документацией.
Комментарии:
1. Я не могу использовать env, поскольку я говорю об экземпляре класса. Кроме того, то, что вы говорите о vars / script, просто неверно, и это точная причина этого сообщения: вы не можете получить доступ к пользовательской глобальной groovy var.
2. И последнее: вы правы, мы можем определить несколько общедоступных методов в groovy scripts, но вы не можете получить к ним доступ из декларативного конвейера, если не добавите закрытие скрипта, чего я не хочу (когда вы определяете один метод с помощью call (), вы можете получить к нему доступ непосредственно из «шагов», которыекрасивее)
3. В представленном случае (myVar — это строка) мой пример работает «из коробки», поскольку переменные env всегда являются строками. В случае beans у вас есть возможность сериализовать, а затем десериализовать ваш объект. Во всех остальных случаях вам придется переосмыслить структуру конвейера и создать объект непосредственно в глобальном скрипте. Мне все еще неясно, почему вы не можете (или не хотите) использовать для этого параметры.
4. Спасибо за ваш обновленный ответ. Для меня такое поведение не имеет смысла, нам приходится создавать экземпляр много раз, мы должны иметь возможность достичь глобальной области видимости из функции, определенной в /vars .
5. Кроме того, я не понимаю интереса указывать «шаги» в качестве параметра, поскольку мы можем использовать функцию groovy, которая позволяет нам объявлять класс с доступом к глобальной области видимости, как описано в первом примере ссылки на документацию, которую вы дали. Может быть, интересно сохранить «состояние» конкретных шагов, но, похоже, это плохая практика в любом случае. ИМХО, в идеале класс должен быть полон статических функций, мы не можем этого сделать только потому, что мы потеряли бы доступ к глобальной области видимости со статическим (sh, echo, …). Что вы думаете ?