我在 jenkinsfile 中使用了一个类,这里是它的简化版本:
class TestBuild {
def build(jenkins) {
jenkins.script {
jenkins.sh(returnStdout: true, script: "echo build")
}
}
}
我供应
this
在 jenkinsfile 中使用它时作为 jenkins 参数。在这里模拟具有 script 和 sh 的 jenkins 对象的最佳方法是什么?谢谢你的帮助
最佳答案
前一周我遇到了类似的问题,我想出了这个:
import org.jenkinsci.plugins.workflow.cps.CpsScript
def mockCpsScript() {
return [
'sh': { arg ->
def script
def returnStdout
// depending on sh is called arg is either a map or a string vector with arguments
if (arg.length == 1 && arg[0] instanceof Map) {
script = arg[0]['script']
returnStdout = arg[0]['returnStdout']
} else {
script = arg[0]
}
println "Calling sh with script: ${script}"
},
'script' : { arg ->
arg[0]()
},
] as CpsScript
}
并与您的脚本一起使用(使用未命名的 sh 调用扩展):
class TestBuild {
def build(jenkins) {
jenkins.script {
jenkins.sh(returnStdout: true, script: "echo build")
jenkins.sh("echo no named arguments")
}
}
}
def obj = new TestBuild()
obj.build(mockCpsScript())
它输出:
[Pipeline] echo
Calling sh with script: echo build
[Pipeline] echo
Calling sh with script: echo no named arguments
现在这个它自己不是很有用,但是很容易添加定义模拟方法行为的逻辑,例如,这个版本控制 readFile 返回的内容,具体取决于正在读取的目录和文件:
import org.jenkinsci.plugins.workflow.cps.CpsScript
def mockCpsScript(Map<String, String> readFileMap) {
def currentDir = null
return [
'dir' : { arg ->
def dir = arg[0]
def subClosure = arg[1]
if (currentDir != null) {
throw new IllegalStateException("Dir '${currentDir}' is already open, trying to open '${dir}'")
}
currentDir = dir
try {
subClosure()
} finally {
currentDir = null
}
},
'echo': { arg ->
println(arg[0])
},
'readFile' : { arg ->
def file = arg[0]
if (currentDir != null) {
file = currentDir + '/' + file
}
def contents = readFileMap[file]
if (contents == null) {
throw new IllegalStateException("There is no mapped file '${file}'!")
}
return contents
},
'script' : { arg ->
arg[0]()
},
] as CpsScript
}
class TestBuild {
def build(jenkins) {
jenkins.script {
jenkins.dir ('a') {
jenkins.echo(jenkins.readFile('some.file'))
}
jenkins.echo(jenkins.readFile('another.file'))
}
}
}
def obj = new TestBuild()
obj.build(mockCpsScript(['a/some.file' : 'Contents of first file', 'another.file' : 'Some other contents']))
这输出:
[Pipeline] echo
Contents of first file
[Pipeline] echo
Some other contents
如果您需要使用 currentBuild 或类似的属性,那么您可能需要在闭包强制之后分配这些属性:
import org.jenkinsci.plugins.workflow.cps.CpsScript
def mockCpsScript() {
def jenkins = [
// same as above
] as CpsScript
jenkins.currentBuild = [
// Add attributes you need here. E.g. result:
result:null,
]
return jenkins
}
关于jenkins - 模拟 Jenkins 管道步骤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50165079/