在Jenkins声明流水线中与矩阵并行运行非矩阵阶段

时间:2020-09-14 04:47:40

标签: jenkins jenkins-declarative-pipeline

我正在转换企业版本,使其使用“矩阵”指令(https://www.jenkins.io/blog/2019/11/22/welcome-to-the-matrix/),但在优化它时遇到了麻烦。在矩阵前的世界中,我们有一个构建步骤(生成jar),然后是并行的“打包”步骤(生成linux和Windows发行版),本质上是一个“系统测试”阶段(在Windows上执行Windows和linux发行版)各种JVM),我们在打包和系统测试阶段进行了一些“代码质量”检查。

其中许多似乎很适合使用“矩阵”。因此,“打包”显然是构建Windows和Linux平台的矩阵。而“系统测试”是平台和jvm的另一个双轴矩阵。我可以轻松地使一个矩阵跟随另一个矩阵。到目前为止,一切都很好。

但是,我坚持将“代码质量”作为离群值。有没有一种方法可以使那些阶段与矩阵运行并行进行。创建构建后,它们是独立的(它们无需等待打包)。它们也很耗时,因此在两个矩阵阶段连续运行它们会使构建时间更长。詹金斯(Jenkins)抱怨如果将矩阵放在并行阶段中。

关于如何与矩阵并行运行非矩阵阶段的任何想法?

2 个答案:

答案 0 :(得分:0)

我有一个针对自己问题的解决方法。

根据文档(https://www.jenkins.io/doc/book/pipeline/syntax/#declarative-matrix),我无法找到所需的内容。 “矩阵中的每个单元都可以包含一个或多个阶段,使用该单元的配置可以依次运行。请注意,一个阶段必须只有一个步骤,阶段,并行或矩阵中的一个,并且不能嵌套一个如果该阶段指令嵌套在并行或矩阵块本身中,则该指令中的并行或矩阵块。”

但是...。你可以作弊。我能够将矩阵转换为通用调度队列。也就是说,每个组合都会调用N个阶段-对我来说是2个阶段,我称它们为“准备”和“执行”。我传入一个附加的“ matrixtype”参数。matrixtype为矩阵本身获取1值,以及为非矩阵的每一行获取附加值。然后,我使用矩阵“排除”来确保非矩阵行仅执行一次。有效地,这会将非矩阵折叠成按矩阵类型区分的矩阵。

Original (parallel-stages in series with a subsequent matrix)
    stage {
        parallel {
           stage("alpha") {
                alpha(..)
           }
           stage("beta") {
               beta(..)
           }
           // etc
       }
    }
    stage {
        matrix {
            axes {
                axis {
                    name 'ORIGAXIS'
                    values 'FOO','BAR','BAZ'
                }
            }
            stages {
               stage("First") {
                  originalFirst( ...)
               }
               stage("Second") {
                  originalSecond(...)
               }
            }
         }
      }

Replacement (parallel folded into matrix)
    stage {
        matrix {
            axes {
                axis {
                    name 'MATRIXTYPE
                    values 'ORIGINAL', 'ALPHA', 'BETA'
                axis {
                    name 'ORIGAXIS'
                    values 'FOO','BAR','BAZ'
                }
                excludes {
                    // Execute Alpha and Beta only once (during 'FOO')
                    exclude {
                        axis {
                            name 'MATRIXTYPE'
                            values 'ALPHA', 'BETA'
                        }
                        axis {
                            name 'ORIGAXIS'
                            values 'BAR','BAZ'
                        }
                    }
                }
            }
            stages {
               stage("First") {
                  dispatchFirst( "${MATRIXTYPE}", ...)
               }
               stage("Second") {
                  dispatchSecond( "${MATRIXTYPE}", ...)
               }
            }
         }
      }

然后,dispatchFirst(..)和dispatchSecond(..)是共享库中检查矩阵类型并调用originalFirst(..),originalSecond(..),alpha(..),beta( ..)或视情况而定。它有点笨拙,相当于将并行阶段塞入矩阵,但它可以工作。而且,您可以获得并行化(构建速度优化)的好处

希望在将来会有更优雅的东西。

答案 1 :(得分:0)

我想出了一种恕我直言的“更好”的解决方案:

stage {
    matrix {
        axes {
            axis {
                name 'ORIGAXIS'
                values 'ALPHA','BETA','BAR','BAZ'
            }
        }
        stages {
           stage ("alpha") {
               when { expression { env.ORIGAXIS == "ALPHA" } }
               steps {
                   alpha()
               }           
           stage ("beta") {
               when { expression { env.ORIGAXIS == "BETA" } }
               steps {
                   beta()
               }
           }
           stage ("Tests") {
               when { allOf
                   expression { env.ORIGAXIS != "ALPHA" }
                   expression { env.ORIGAXIS != "BETA" }
               }
               stages {
                   stage("First") {
                      originalFirst( ...)
                    }
                   stage("Second") {
                      originalSecond(...)
                   }
                }
            }
     }
}

当然,最终的布局并不完美。但是,它工作起来并不麻烦,而且仍然易于维护。