加载Groovy文件时捕获异常

时间:2020-03-14 07:29:54

标签: groovy jenkins-pipeline jenkins-groovy

我有以下3个groovy文件:

A.groovy:

// ...
stage("Test")
{
    throw new Exception("This script fails")
}

B.groovy:

// ...
stage("Test")
{
    // Nothing, want this to pass
}

main.groovy:

// ...
m = [:]
status = [:]
scripts = ["A", "B"]
for script in scripts
{
    m["${script}"] = 
    {
        stage("${script}")
        {
            try
            {
                 load "${script}.groovy"
                 status["${script}"] = true
            }
            catch (Exception e)
            {
                 status["${script}"] = false   
            }
        }
    }
}

parallel m

for result_iterator in status:
    print "${result_iterator.key} resulted in ${result_iterator.value}"

上面的代码是真实代码的草图=) 当我运行main.groovy在状态字典中查看结果时,我只会看到B。A抛出异常,因此它没有将自身添加到字典中。我有办法以某种方式捕获A的异常吗?

1 个答案:

答案 0 :(得分:3)

问题1

您被Groovy闭包捕获超出其范围的变量的方式所困扰。闭包内部对script的引用将在运行闭包时收到script的值,即script最后一个值。因此,这两个闭包实际上都加载“ B.groovy” ,并且永远不会引发异常!

修复很简单,只需在循环内部创建一个捕获script当前值的局部变量即可:

for( script in scripts ) {
    def theScript = script
    // Now only use theScript inside of the closure!
}

问题2

您没有从status线程序列化对parallel变量的写访问。这可能会导致非常令人讨厌且难以复制的错误。

解决方法是使用Map.asSynchronized()创建一个synchronized map

status = [:].asSynchronized()

完成“ main.groovy”修复

m = [:]
status = [:].asSynchronized()  // because multiple threads write to this variable
scripts = ["A", "B"]

for( script in scripts ) {
    def theScript = script  // Important to pass the current value into the closure!

    m[ theScript ] = {
        stage( theScript ) {
            try {
                 load "${theScript}.groovy"
                 status[ theScript ] = true
            }
            catch (Exception e) {
                 status[ theScript ] = false   
            }
        }
    }
}

parallel m

for( result_iterator in status ) {
    print "${result_iterator.key} resulted in ${result_iterator.value}"
}

注意:我还删除了不必要的字符串插值。