Продолжил поиск путей для достижения этой цели.Даже написал плагин jenkins, который предоставляет глобальную переменную cpsScript
.К сожалению, вам нужен экземпляр, чтобы обеспечить контекст для этого вызова, поэтому он бесполезен.
Таким образом, в качестве «наименее плохого решения» (tm) я создал класс, который я назвал ScriptContext
, который я могу использовать в качестве базового класса для своих конвейерных классов (он реализует Serializable
).
Когда вы пишете свой конвейерный скрипт, вы либо передаете его CpsScript
статически один раз:
ScriptContext.script = this
Или, если вы его получили (обязательно вызовите super()
):
new MyPipeline(this)
Если ваш класс является производным от ScriptContext
, ваша работа завершена.Все будет работать так, как будто вы не создали класс, а просто использовали автоматическое преобразование.Если вы используете какие-либо функции уровня CpsScript, кроме println, вы можете добавить их и здесь.
В любом другом месте вы можете просто вызвать ScriptContext.script
, чтобы получить экземпляр скрипта.
Код класса (большинство комментариев удалено, чтобы сделать его максимально коротким):
package ...
import org.jenkinsci.plugins.workflow.cps.*
class ScriptContext implements Serializable {
protected static CpsScript _script = null
ScriptContext(CpsScript script = null) {
if (!_script && script) {
_script = script
}
}
ScriptContext withScript(CpsScript script) {
setScript(script)
this
}
static void setScript(CpsScript script) {
if (!_script && script) {
_script = script
}
}
static CpsScript getScript()
{
_script
}
// functions defined in CpsScript itself are not automatically found
void println(what) {
_script.println(what)
}
/**
* For derived classes we provide missing method functionality by trying to
* invoke the method in script context
*/
def methodMissing(String name, args) {
if (!_script) {
throw new GroovyRuntimeException('ScriptContext: No script instance available.')
}
return _script.invokeMethod(name, args)
}
/**
* For derived classes we provide missing property functionality.
* Note: Since it's sometimes unclear whether a property is an actual property or
* just a function name without brackets, use evaluate for this instead of getProperty.
* @param name
* @param args
* @return
*/
def propertyMissing(String name) {
if (!_script) {
throw new GroovyRuntimeException('ScriptContext: No script instance available.')
}
_script.evaluate(name)
}
/**
* Wrap in node if needed
* @param body
* @return
*/
protected <V> V node(Closure<V> body) {
if (_script.env.NODE_NAME != null) {
// Already inside a node block.
body()
} else {
_script.node {
body()
}
}
}
}