存在并行调用时出现奇怪的阶段行为

问题描述 投票:0回答:1

我的管道中有一些阶段可能会自行失败,但不会使构建过程失败。我希望这个阶段被指示为失败,所以将它们包裹在

try
-
catch
块中。然而,有些阶段一直显示为成功,而实际上却失败了。经过一些研究,我能够查明问题所在:所有“错误显示”阶段都有
parallel
调用(即使
parallel
中的块完全不做任何事情,效果也会发生)。最后,我能够将问题归结为这个最小的可重现示例:

node {
    try {
        stage("A") {
            error "E"
        }
    } catch(e) {}
    
    try {
        stage("B") {
            parallel a : {}, b : {}
            error "E"
        }
    } catch(e) {}
}

这里

A
阶段将显示为失败,
B
阶段将显示为成功。交换它们会产生相同的结果(
A
失败;
B
成功)。将
error "E"
更改为
throw new Exception("E")
没有任何区别。在这两种情况下,都可以毫无问题地抛出和捕获异常,只影响舞台外观。

在那之后,我尝试执行多个类似于

B
的阶段,结果证明每个阶段最初都显示为成功(即使它失败了)。当下一阶段完成时,它也显示为成功,但同时前一阶段开始显示为失败。当第三阶段完成时,第二阶段变为失败,依此类推直到最后阶段。最后一个阶段保持成功,因为没有下一阶段来“更新”它。从逻辑上讲,这可以通过在链的最后阶段之后插入一个虚拟的
parallel
调用来解决:

...
parallel foo : {}
...

问题是:

parallel
是怎么回事?我用错了吗还是某种错误?

重要说明:我使用的是 Jenkins 2.150.2,无法迁移到更新版本。

jenkins jenkins-pipeline jenkins-groovy
1个回答
0
投票

我认为

parallel
背后的想法一定是关于拥有专用舞台,前后没有任何其他步骤。这种设计在声明式管道中很明显:

pipeline {
    agent any
    stages {
        stage("A"){
            steps{
                catchError( stageResult: 'FAILURE'){
                    error "E"
                }
            }
        }
        stage("B") {
            parallel {
                stage("p1") {
                     steps{
                         catchError( stageResult: 'FAILURE'){
                         error "a"
                         }
                     }
                }
                stage("p2") {
                      steps{
                         catchError( stageResult: 'FAILURE'){
                          echo "b"
                         }
                      }
                }
            }
            //echo "test1" // illegal
        }
        stage("C"){
            steps{
                error "E"
            }
        }
    }
}

如果您尝试在 parallel 之后放置任何内容,将会出现语法错误。 所以要回答这个问题:你必须使用不可预测的步骤序列,所以你会得到奇怪的结果。 尽管如此,正如我在 Jenkins 实例中看到的那样,只有 STAGE VIEW 插件的结果很奇怪。所以你有失败阶段的绿色矩形,但整个工作状态实际上应该是失败的。

回到您的脚本示例:

node {
        stage("A") {
            catchError(stageResult: 'FAILURE'){
            error "E"
            }
        }
        stage("B") {
            catchError( stageResult: 'FAILURE'){
            parallel a : {stage("p1"){error "a"}}, b : {stage("p2"){echo "b"}}
            }
        }
        stage("C"){
            error "E"
        }
}

使用

catchError
步骤更干净。 要在并行之后放置任何东西,您应该为此目的使用单独的阶段。 如果您为并行保留单独的阶段,您将获得一致的 Jenkins 行为。

© www.soinside.com 2019 - 2024. All rights reserved.