Получить экземпляр CpsScript в коде workflow-cps? - PullRequest
0 голосов
/ 13 сентября 2018

В настоящее время кодирую много интересного для очень специфических сценариев Дженкинса.

Проблема в том, что мне нужно отслеживать текущий CpsScript -экземпляр для контекста (получение свойств, среды и т. Д.) И его invokeMethod (шаги рабочего процессаи тому подобное).

В настоящее время это означает, что я передаю this в скриптовом конвейерном скрипте на свой класс ввода, и оттуда он передается каждому классу отдельно, что очень раздражает .

Экземпляр сценария создается CpsFlowExecution и хранится в экземпляре Continuable и CpsThreadGroup, ни один из которых не позволяет получить его.

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

Так что вопрос:

Кто-нибудь знает способ отслеживать CpsScript -экземпляр, который не требует, чтобы я передавал его каждому новому классу, который я создаю?(Или в качестве альтернативы: получить его из любого места - это действительно должно быть так сложно?)

1 Ответ

0 голосов
/ 18 сентября 2018

Продолжил поиск путей для достижения этой цели.Даже написал плагин 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()
            }
        }
    }
}
...