为什么这个Jenkins管道代码没有成功?

时间:2016-10-28 12:44:23

标签: jenkins groovy jenkins-pipeline

这是我的情况:我的一个项目由多个子项目组成,大致分为前端和后端,它们位于subversion存储库的不同位置。

我将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。正如您所看到的,我将每个属性设置为null,因为我在某个地方读取,这可以防止这种行为。你能帮我解决一下这个问题并解释一下,这里到底发生了什么?

谢谢!

1 个答案:

答案 0 :(得分:0)

我认为这是for循环中已知的Jenkins错误:

https://issues.jenkins-ci.org/browse/JENKINS-27421

但是.each样式循环也有一个已知的错误

https://issues.jenkins-ci.org/browse/JENKINS-26481

所以目前看起来你无法在Jenkins管道中迭代地图。我建议创建一个列表作为解决方法,并使用"经典循环"迭代它。式:

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 }
}