Конструктор не вызывается в общих библиотеках Jenkins

Я пытаюсь разработать общие библиотеки и имею следующую структуру каталогов

  • src/com/mycomapny
    • MyTest.groovy
  • vars
    • test.groovy
  • Jenkinsfile

мой Jenkinsfile вызывает только метод, доступный в test.groovy с обязательным вводом. который импортирует MyTest и создает объект и вызывает конструктор, за которым следует фактический метод, который выполняет функции, доступные в файле MyTest.groovy.

Здесь класс конструктора никогда не вызывается из глобальных vars / test.groovy

Я попытался вызвать класс и метод из Groovy, он работает нормально, но когда я вызываю его из jenkinsfile, он не работает. Я не знаю, почему я не могу вызвать конструктор и чего мне не хватает.

Я поместил @NonCPS в метод выше test.groovy, но он все еще не работает.

//MyTest.groovy
package com.mycompany

class MyTest implements Serializable {
    public _notification

    MyTest(Closure content) {
        notification = [:]
        content.resolveStrategy = Closure.DELEGATE_FIRST
        content.delegate = notification
        content()
        println("Entered Constructor")
        this._notification = notification
    }

}

//test.groovy
import com.mycopany.MyTest
def notify(Closure content) {
    println("This is line i am getting in the output but nothing after that")
    MyTest tester = new MyTest(content)
    println(tester._notification.colorcode)
} 

//Jenkinsfile
@library("MysharedLibrary@master") _
pipeline{
    stages {
         stage {
             steps {
                 test.notify {
                      buildno = 12
                      jobname = "Mytest"
                      colorcode = "Blue"
                 }
             }
         }
    }
}

здесь я просто хочу вызвать конструктор из файла jenkins и распечатать значение входного значения в моем vars / test.groovy.

EDIT1: когда я использую @NonCPS выше метода def nofity, моя сборка становится успешной, но я не получаю ничего, кроме оператора печати в первой строке метода уведомления.

Если я не использую @NonCPS, я получаю следующее исключение

Error when executing always post condition:
com.cloudbees.groovy.cps.impl.CpsCallableInvocation

hudson.remoting.ProxyException:com.cloudbees.groovy.cps.impl.CpsCallableInvocation
Finished: FAILURE

person yashwanth ssc    schedule 01.07.2019    source источник
comment
Что «не работает»? Ошибки / трассировки?   -  person cfrick    schedule 01.07.2019
comment
Я ничего не получаю в выводе, когда использую @NonCPS, указанный выше, метод def notify и сборка прошла успешно. Если я не использую @NonCPS, я получаю следующую ошибку Ошибка при выполнении условия публикации всегда: com.cloudbees.groovy.cps.impl.CpsCallableInvocation hudson.remoting.ProxyException: com.cloudbees.groovy.cps.impl.CpsCallableInvocation   -  person yashwanth ssc    schedule 01.07.2019


Ответы (1)


Вы видите эту ошибку, потому что вызываете закрытие внутри конструктора. Вместо этого вы должны извлечь его в отдельный метод. Конструктор следует использовать для инициализации объекта значениями, переданными во время инициализации. Например, обычной практикой является передача ссылки на объект WorkflowScript, поэтому вы можете использовать шаги конвейера, такие как echo.

Обратите внимание на следующие изменения в коде общей библиотеки:

src / com / mycompany / MyTest.groovy

package com.mycompany

class MyTest {
  final Map notification = [:]
  final Script script

  MyTest(Script script) {
    this.script = script
  }

  def notify(Closure content) {
    processContent(content)
    script.echo "Notification processed = ${notification}"
  }

  def processContent(Closure content) {
    content.resolveStrategy = Closure.DELEGATE_FIRST
    content.delegate = notification
    content()
  }
}

vars / test.groovy

import com.mycompany.MyTest
import groovy.transform.Field

@Field
final MyTest tester = new MyTest(this)

def notify(Closure content) {
    println("This is line i am getting in the output but nothing after that")
    tester.notify(content)
    println(tester.notification.colorcode)
}

Jenkinsfile

pipeline {
    agent any

    stages {
         stage("Test") {
             steps {
                 script {
                     test.notify {
                          buildno = 12
                          jobname = "Mytest"
                          colorcode = "Blue"
                     }
                 }
             }
         }
    }
}

Выход:

[Pipeline] Start of Pipeline
[Pipeline] node
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Test)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
This is line i am getting in the output but nothing after that
[Pipeline] echo
Notification processed = [buildno:12, jobname:Mytest, colorcode:Blue]
[Pipeline] echo
Blue
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline

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

person Szymon Stepniak    schedule 01.07.2019
comment
Спасибо за ответ. Я новичок в написании конвейеров и разделяемых библиотек. Этот принцип применим только к закрытию или ко всему остальному. потому что я пытался использовать конструкторы для передачи нормальных значений с помощью конструктора, даже который у меня тоже не работал. В очередной раз благодарим за помощь. пожалуйста, предложите любые ссылки для чтения. Я мало что нахожу о разделяемых библиотеках - person yashwanth ssc; 01.07.2019