【问题标题】:Running non-matrix stages in parallel to a matrix in Jenkins declarative-pipeline在 Jenkins 声明式管道中与矩阵并行运行非矩阵阶段
【发布时间】:2020-09-14 04:47:40
【问题描述】:

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

其中大部分似乎都适合使用“矩阵”。因此,“包装”显然是一个制作 Windows 和 linux 平台的矩阵。而“系统测试”是另一个平台和jvm的双轴矩阵。我可以轻松地使一个矩阵跟随另一个矩阵。到目前为止,一切顺利。

但是,我坚持将“代码质量”作为异常值。有没有办法让这些阶段与矩阵运行平行。一旦构建创建它们是独立的(它们不需要等待打包)。它们也很耗时,因此使用两个矩阵阶段连续运行它们会使构建时间更长。如果您将矩阵放入并行阶段,Jenkins 会抱怨。

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

【问题讨论】:

    标签: jenkins jenkins-declarative-pipeline


    【解决方案1】:

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

    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(...)
                       }
                    }
                }
         }
    }
    

    当然,最终的布局并不完美。但是,它确实有效,没有那么繁琐,而且仍然易于维护。

    【讨论】:

    • 这看起来很有趣。我还没有尝试过,但它不会创建一个笛卡尔坐标系,其中你有 alpha/beta/bar/baz 的垂直矩阵,并且在每个矩阵中都有一个 alpha/beta/bar/baz 阶段。当然,条形阶段仅在条形矩阵行等中执行,因此它确实执行正确并且代码更少。但正如你所说,显示可能很傻。
    • 显示很愚蠢...但是纯声明式管道,因此您可以利用语法验证的优势(也意味着更好的用户体验)。但无论如何,我后来注意到我不能在我的情况下使用矩阵:矩阵轴不能是可变的。
    • .. 一个切线... 矩阵轴不能是可变的,但您可以指定所有可能的,然后有条件地关闭您不想要的那些 - 伪变量
    【解决方案2】:

    我有自己的问题的解决方法。

    根据文档 (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( ..) 或适当的无操作。它有点笨拙,相当于将并行阶段硬塞到矩阵中,但它确实有效。并且,您将获得并行化的好处(构建速度优化)

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-20
      • 1970-01-01
      • 1970-01-01
      • 2021-08-02
      • 2017-12-03
      相关资源
      最近更新 更多