运行 与 Jenkins 声明式管道中的矩阵并行的非矩阵阶段
Running non-matrix stages in parallel to a matrix in Jenkins declarative-pipeline
我正在转换我们的企业构建,以便它使用 'matrix' 指令 (https://www.jenkins.io/blog/2019/11/22/welcome-to-the-matrix/),但在优化它时遇到了问题。在 pre-matrix 世界中,我们有一个构建步骤(生成 jar),然后是并行的 'package' 步骤(生成 linux 和 windows 发行版),本质上是 'system test' 阶段(在各种 JVM 上执行 windows 和 linux 发行版),我们在打包和系统测试阶段并行进行一些 'code quality' 检查。
其中大部分似乎适合使用 'matrix'。因此,'packaging' 显然是用于制作 windows 和 linux 平台的矩阵。而'system test'又是一个platform和jvm的双轴矩阵。我可以轻松地使一个矩阵跟随另一个矩阵。到目前为止,还不错。
但是,我坚持认为 'code quality' 是异常值。有没有办法 运行 那些平行于矩阵 运行 的阶段。一旦创建构建,它们就是独立的(它们不需要等待打包)。它们也很耗时,因此 运行 将它们与两个矩阵相串联会使构建时间更长。如果将矩阵放入并行阶段,Jenkins 会抱怨。
关于如何 运行 非矩阵阶段与矩阵并行的任何想法?
我有一个 work-around 我自己的问题。
根据文档 (https://www.jenkins.io/doc/book/pipeline/syntax/#declarative-matrix),我所寻找的是不可能的。 “矩阵中的每个单元格都可以包含一个或多个阶段 运行 按顺序使用该单元格的配置。请注意,一个阶段必须具有且只有一个步骤、阶段、并行或矩阵。它不是如果阶段指令嵌套在并行或矩阵块本身中,则可以在阶段指令中嵌套并行或矩阵块。"
但是....你可以作弊。我能够将矩阵变成一个通用的调度队列。即每个组合调用 N 个阶段 - 对我来说,2 我称它们为“准备”和“执行”。我传递了一个额外的“matrixtype”参数。matrixtype 为矩阵本身获取 1 个值,以及为 non-matrix 的每一行获取附加值。然后我使用矩阵 'excludes' 来确保 non-matrix 行只执行一次。实际上,这将非矩阵折叠成按矩阵类型区分的矩阵。
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(..) 或 no-op 视情况而定。它有点笨拙,相当于将并行阶段硬塞进矩阵,但它确实有效。而且,您可以获得并行化的好处 (build speed-optimization)
希望以后能有更优雅的东西
我想出了一个有点恕我直言的“更好”的解决方案:
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(...)
}
}
}
}
}
当然,最终的布局并不完美。但是,它有效,没有那么麻烦并且仍然易于维护。
我正在转换我们的企业构建,以便它使用 'matrix' 指令 (https://www.jenkins.io/blog/2019/11/22/welcome-to-the-matrix/),但在优化它时遇到了问题。在 pre-matrix 世界中,我们有一个构建步骤(生成 jar),然后是并行的 'package' 步骤(生成 linux 和 windows 发行版),本质上是 'system test' 阶段(在各种 JVM 上执行 windows 和 linux 发行版),我们在打包和系统测试阶段并行进行一些 'code quality' 检查。
其中大部分似乎适合使用 'matrix'。因此,'packaging' 显然是用于制作 windows 和 linux 平台的矩阵。而'system test'又是一个platform和jvm的双轴矩阵。我可以轻松地使一个矩阵跟随另一个矩阵。到目前为止,还不错。
但是,我坚持认为 'code quality' 是异常值。有没有办法 运行 那些平行于矩阵 运行 的阶段。一旦创建构建,它们就是独立的(它们不需要等待打包)。它们也很耗时,因此 运行 将它们与两个矩阵相串联会使构建时间更长。如果将矩阵放入并行阶段,Jenkins 会抱怨。
关于如何 运行 非矩阵阶段与矩阵并行的任何想法?
我有一个 work-around 我自己的问题。
根据文档 (https://www.jenkins.io/doc/book/pipeline/syntax/#declarative-matrix),我所寻找的是不可能的。 “矩阵中的每个单元格都可以包含一个或多个阶段 运行 按顺序使用该单元格的配置。请注意,一个阶段必须具有且只有一个步骤、阶段、并行或矩阵。它不是如果阶段指令嵌套在并行或矩阵块本身中,则可以在阶段指令中嵌套并行或矩阵块。"
但是....你可以作弊。我能够将矩阵变成一个通用的调度队列。即每个组合调用 N 个阶段 - 对我来说,2 我称它们为“准备”和“执行”。我传递了一个额外的“matrixtype”参数。matrixtype 为矩阵本身获取 1 个值,以及为 non-matrix 的每一行获取附加值。然后我使用矩阵 'excludes' 来确保 non-matrix 行只执行一次。实际上,这将非矩阵折叠成按矩阵类型区分的矩阵。
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(..) 或 no-op 视情况而定。它有点笨拙,相当于将并行阶段硬塞进矩阵,但它确实有效。而且,您可以获得并行化的好处 (build speed-optimization)
希望以后能有更优雅的东西
我想出了一个有点恕我直言的“更好”的解决方案:
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(...)
}
}
}
}
}
当然,最终的布局并不完美。但是,它有效,没有那么麻烦并且仍然易于维护。