为什么这个 Jenkins Pipeline 代码不成功?
Why does this Jenkins Pipeline code not succeed?
这是我的情况:我的一个项目由多个子项目组成,大致分为前端和后端,它们位于颠覆存储库中的不同位置。
我将 checkout
插件提取到一个函数中,该函数已经为结帐正确参数化:
def svn(String url, String dir = '.') {
checkout([
$class: 'SubversionSCM',
locations: [[
remote: url,
credentialsId: '...'
local: dir,
]],
workspaceUpdater: [$class: 'UpdateUpdater']
])
}
这样,我就可以通过这种方式(简化)进行结帐:
stage "1. Build"
parallel (
"Backend": { node {
svn('https://svn.acme.com/Backend/trunk')
sh 'gradle build'
}},
"Frontend": { node {
svn('https://svn.acme.com/Frontend/trunk')
sh 'gradle build'
}}
)
同时检出导致 Jenkins 遇到变更集 xml 文件的问题,据我从堆栈跟踪中猜测。
由于我还想重用项目名称及其 svn url,我继续迭代地图并连续检出,并在第一阶段存储文件以进行后续并行构建-仅阶段:
stage "1. Checkout"
node {
[
'Backend': 'https://svn.acme.com/Backend/trunk',
'Frontend': 'https://svn.acme.com/Frontend/trunk',
].each { name, url ->
// Checkout in subdirectory
svn(url, name)
// Unstash by project name
dir(name) { stash name }
}
}
stage "2. Build"
// ...
不知何故 Jenkins 的管道不支持这个,所以我使用了一个简单的 for-in 循环:
node {
def projects = [
'Backend': '..'
// ...
]
for ( project in projects ) {
def name = project.getKey()
def url = project.getValue()
svn(url, name)
dir(name) { stash name }
}
project = projects = name = url = null
}
效果不佳并退出构建并出现异常:java.io.NotSerializableException: java.util.LinkedHashMap$Entry
。如您所见,我将每个 属性 设置为空,因为我在某处读到,这可以防止这种行为。你能帮我解决这个问题并解释一下,这里到底发生了什么吗?
谢谢!
我认为这是 for 循环中的一个已知 Jenkins 错误:
https://issues.jenkins-ci.org/browse/JENKINS-27421
但是 .each 样式循环也存在一个已知错误
https://issues.jenkins-ci.org/browse/JENKINS-26481
因此,目前您似乎无法在 Jenkins 管道中迭代地图。我建议创建一个列表作为解决方法,并使用 "classic loop" 样式对其进行迭代:
def myList = ["Backend|https://svn.acme.com/Backend/trunk", "Frontend|https://svn.acme.com/Frontend/trunk"]
for (i = 0; i < myList.size(); i++) {
//get current list item : myList[i] and split at pipe | ->escape pipe with \
def (name, url) = myList[i].tokenize( '\|' )
//do operations
svn(url, name)
dir(name) { stash name }
}
这是我的情况:我的一个项目由多个子项目组成,大致分为前端和后端,它们位于颠覆存储库中的不同位置。
我将 checkout
插件提取到一个函数中,该函数已经为结帐正确参数化:
def svn(String url, String dir = '.') {
checkout([
$class: 'SubversionSCM',
locations: [[
remote: url,
credentialsId: '...'
local: dir,
]],
workspaceUpdater: [$class: 'UpdateUpdater']
])
}
这样,我就可以通过这种方式(简化)进行结帐:
stage "1. Build"
parallel (
"Backend": { node {
svn('https://svn.acme.com/Backend/trunk')
sh 'gradle build'
}},
"Frontend": { node {
svn('https://svn.acme.com/Frontend/trunk')
sh 'gradle build'
}}
)
同时检出导致 Jenkins 遇到变更集 xml 文件的问题,据我从堆栈跟踪中猜测。
由于我还想重用项目名称及其 svn url,我继续迭代地图并连续检出,并在第一阶段存储文件以进行后续并行构建-仅阶段:
stage "1. Checkout"
node {
[
'Backend': 'https://svn.acme.com/Backend/trunk',
'Frontend': 'https://svn.acme.com/Frontend/trunk',
].each { name, url ->
// Checkout in subdirectory
svn(url, name)
// Unstash by project name
dir(name) { stash name }
}
}
stage "2. Build"
// ...
不知何故 Jenkins 的管道不支持这个,所以我使用了一个简单的 for-in 循环:
node {
def projects = [
'Backend': '..'
// ...
]
for ( project in projects ) {
def name = project.getKey()
def url = project.getValue()
svn(url, name)
dir(name) { stash name }
}
project = projects = name = url = null
}
效果不佳并退出构建并出现异常:java.io.NotSerializableException: java.util.LinkedHashMap$Entry
。如您所见,我将每个 属性 设置为空,因为我在某处读到,这可以防止这种行为。你能帮我解决这个问题并解释一下,这里到底发生了什么吗?
谢谢!
我认为这是 for 循环中的一个已知 Jenkins 错误:
https://issues.jenkins-ci.org/browse/JENKINS-27421
但是 .each 样式循环也存在一个已知错误
https://issues.jenkins-ci.org/browse/JENKINS-26481
因此,目前您似乎无法在 Jenkins 管道中迭代地图。我建议创建一个列表作为解决方法,并使用 "classic loop" 样式对其进行迭代:
def myList = ["Backend|https://svn.acme.com/Backend/trunk", "Frontend|https://svn.acme.com/Frontend/trunk"]
for (i = 0; i < myList.size(); i++) {
//get current list item : myList[i] and split at pipe | ->escape pipe with \
def (name, url) = myList[i].tokenize( '\|' )
//do operations
svn(url, name)
dir(name) { stash name }
}