Доступ к переменным внутри тела закрытия конвейера jenkins

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

import java.security.MessageDigest

def call(body) {
    def config = [:]
    body.resolveStrategy = Closure.DELEGATE_FIRST
    body.delegate = config

    ws(getWsHash(config.length ?: 10)) {
        body()
    }
}

def getWsHash(length) {
    def md5Hash = MessageDigest.getInstance("MD5").digest("${env.JOB_NAME}_${env.EXECUTOR_NUMBER}".bytes).encodeHex().toString()
    return md5Hash.substring(0,10)
}

который я хочу использовать следующим образом:

node('windows') {

    wsHash {
        stage('Checkout') {
            checkout scm
        }

        stage('Build') {
            bat '.\\src\\Build.cmd'
        }
    }
}

Однако это не удается, потому что переменная scm имеет значение null. Мне удалось исправить это, изменив на это:

node('windows') {

    def scm = scm

    wsHash {
        stage('Checkout') {
            checkout scm
        }

        stage('Build') {
            bat '.\\src\\Build.cmd'
        }
    }
}

Однако это неуклюже и не работает для всех случаев. Например, мы также используем артефакты, и при попытке использовать это:

def server = Artifactory.server('advancedcsg')

Я получаю следующее исключение:

java.lang.NullPointerException: невозможно вызвать метод server() для нулевого объекта

Если я попробую «трюк», выполнив:

def Artifactory = Artifactory

Я получаю это исключение:

java.lang.UnsupportedOperationException: отказ от маршалинга org.codehaus.groovy.runtime.GStringImpl по соображениям безопасности

Может кто-нибудь помочь объяснить, что здесь происходит и что я сделал неправильно?


person caveman_dick    schedule 23.06.2017    source источник


Ответы (1)


Я не знаю конвейерных сценариев Jenkins, но со знанием Groovy и тем, что вы описываете, проблема в том, что вы даете замыкание на wsHash и там устанавливаете делегата на пустую карту (config), поэтому scm запрашивается из него и и возвращает null конечно.

Я предполагаю, что если вы явно назовете параметр it закрытия узла и используете его, он должен работать, например:

node('windows') { windowsNode ->
    wsHash {
        stage('Checkout') {
            checkout windowsNode.scm
        }

        stage('Build') {
            bat '.\\src\\Build.cmd'
        }
    }
}

Другая ошибка, которую вы получаете, ошибка Refusing to marshal, скорее всего, связана с другой частью вашего конвейера, где у вас есть что-то вроде "foo $bar baz", которое является GString, и вместо этого вам нужно String, поэтому вместо этого используйте "foo $bar baz" as String, и динамические части будут немедленно разрешены и преобразованы в простой объект String.

person Vampire    schedule 23.06.2017