5

我正在尝试开发共享库并具有以下目录结构

  • src/com/mycomapny
    • MyTest.groovy
  • 变量
    • test.groovy
  • 詹金斯文件

我的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:当我在方法“def nofity”上方使用@NonCPS 时,我的构建正在成功,但除了通知方法的第一行中的打印语句外,我什么也没得到。

如果我不使用@NonCPS,我会得到以下异常

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

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

1 回答 1

3

您看到此错误是因为您在构造函数中调用了闭包。相反,您应该将其提取到单独的方法中。构造函数应该用于使用在初始化期间传递的值来初始化对象。例如,通常的做法是将引用传递给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()
  }
}

变量/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)
}

詹金斯文件

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

请记住,这只是重构共享管道库代码的一种方式。您的主要目标应该是从类构造函数内部移动闭包调用。将它放在哪里取决于您,以便它最适合您。

于 2019-07-01T08:31:59.590 回答