我的管道中有一些阶段可能会自行失败,但不会使构建过程失败。我希望这个阶段被指示为失败,所以将它们包裹在
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,无法迁移到更新版本。
我认为
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 行为。