脚本化的jenkinsfile并行阶段

5q4ezhmt  于 2022-11-02  发布在  Jenkins
关注(0)|答案(8)|浏览(212)

我尝试使用Groovy DSL编写一个脚本化的Jenkinsfile,它将在一组阶段中具有并行步骤。
下面是我的jenkinsfile:

node {   
stage('Build') {
    sh 'echo "Build stage"'
}

stage('API Integration Tests') {
    parallel Database1APIIntegrationTest: {
        try {
            sh 'echo "Build Database1APIIntegrationTest parallel stage"'
        }
        finally {
            sh 'echo "Finished this stage"'
        }               

    }, Database2APIIntegrationTest: {
        try {
            sh 'echo "Build Database2APIIntegrationTest parallel stage"'
        }
        finally {
            sh 'echo "Finished this stage"'
        }

    }, Database3APIIntegrationTest: {
        try {
            sh 'echo "Build Database3APIIntegrationTest parallel stage"'
        }
        finally {
            sh 'echo "Finished this stage"'
        }
    }
}

stage('System Tests') {
    parallel Database1APIIntegrationTest: {
        try {
            sh 'echo "Build Database1APIIntegrationTest parallel stage"'
        }
        finally {
            sh 'echo "Finished this stage"'
        }               

    }, Database2APIIntegrationTest: {
        try {
            sh 'echo "Build Database2APIIntegrationTest parallel stage"'
        }
        finally {
            sh 'echo "Finished this stage"'
        }

    }, Database3APIIntegrationTest: {
        try {
            sh 'echo "Build Database3APIIntegrationTest parallel stage"'
        }
        finally {
            sh 'echo "Finished this stage"'
        }
    }
}
}

我想有3个阶段:构建、集成测试和系统测试。在这两个测试阶段中,我希望并行执行3组测试,每组测试针对不同的数据库。
我有3个可用的执行者。一个在主程序上,2个代理程序,我希望每个并行步骤都在任何可用的执行者上运行。
我注意到,在运行管道后,我只看到3个阶段,每个阶段都标记为绿色。我不想查看该阶段的日志,以确定该阶段中的任何并行步骤是否成功/不稳定/失败。
我希望看到测试阶段中的3个步骤-标记为绿色、黄色或红色(成功、不稳定或失败)。
我考虑过将测试扩展到它们自己的阶段,但是已经意识到并行阶段不受支持(有人知道是否会支持这一点吗?),所以我不能这样做,因为流水线将花费太长的时间来完成。
任何见解都将不胜感激,谢谢

qgelzfjb

qgelzfjb1#

在Jenkins脚本化管道中,parallel(...)采用一个Map来描述要构建的每个阶段。因此,您可以预先通过编程来构建构建阶段,这种模式允许灵活的串行/并行切换。
我使用了类似的代码,其中prepareBuildStages返回一个Map列表,每个List元素都按顺序执行,而Map描述了该点的并行阶段。

// main script block
// could use eg. params.parallel build parameter to choose parallel/serial 
def runParallel = true
def buildStages

node('master') {
  stage('Initialise') {
    // Set up List<Map<String,Closure>> describing the builds
    buildStages = prepareBuildStages()
    println("Initialised pipeline.")
  }

  for (builds in buildStages) {
    if (runParallel) {
      parallel(builds)
    } else {
      // run serially (nb. Map is unordered! )
      for (build in builds.values()) {
        build.call()
      }
    }
  }

  stage('Finish') {
      println('Build complete.')
  }
}

// Create List of build stages to suit
def prepareBuildStages() {
  def buildStagesList = []

  for (i=1; i<5; i++) {
    def buildParallelMap = [:]
    for (name in [ 'one', 'two', 'three' ] ) {
      def n = "${name} ${i}"
      buildParallelMap.put(n, prepareOneBuildStage(n))
    }
    buildStagesList.add(buildParallelMap)
  }
  return buildStagesList
}

def prepareOneBuildStage(String name) {
  return {
    stage("Build stage:${name}") {
      println("Building ${name}")
      sh(script:'sleep 5', returnStatus:true)
    }
  }
}

产生的配管显示为:

对于并行块中可以嵌套的内容有一定的限制,请参考管道文档以了解确切的细节。不幸的是,大多数参考似乎偏向于声明性管道,尽管它比脚本化的管道灵活得多(恕我直言)。管道示例页面是最有帮助的。

uidvcgyl

uidvcgyl2#

下面是一个基于@Ed Randall的帖子的简单示例,没有循环或函数:

node('docker') {
    stage('unit test') {
        parallel([
            hello: {
                echo "hello"
            },
            world: {
                echo "world"
            }
        ])
    }

    stage('build') {
        def stages = [:]

        stages["mac"] = {
            echo "build for mac"
        }
        stages["linux"] = {
            echo "build for linux"
        }

        parallel(stages)
    }
}

...生成以下结果:

请注意,Map的值不需要是阶段,您可以直接给予步骤。

vatpfxk5

vatpfxk53#

下面是他们文档中的一个示例:

并行执行

上一节中的示例以线性序列跨两个不同平台运行测试。实际上,如果make check执行需要30分钟才能完成,则“测试”阶段现在需要60分钟才能完成!
幸运的是,Pipeline具有并行执行Scripted Pipeline各部分的内置功能,该功能在名称恰当的并行步骤中实现。
重构上面的示例以使用并行步骤:

// Jenkinsfile (Scripted Pipeline)

stage('Build') {
    /* .. snip .. */
}

stage('Test') {
    parallel linux: {
        node('linux') {
            checkout scm
            try {
                unstash 'app'
                sh 'make check'
            }
            finally {
                junit '**/target/*.xml'
            }
        }
    },
    windows: {
        node('windows') {
            /* .. snip .. */
        }
    }
}
atmip9wb

atmip9wb4#

为了简化@Ed Randall的答案,请记住这是Jenkinsfile脚本化的(不是声明性的)

stage("Some Stage") {
    // Stuff ...
}

stage("Parallel Work Stage") {

    // Prealocate dict/map of branchstages
    def branchedStages = [:]

    // Loop through all parallel branched stage names
    for (STAGE_NAME in ["Branch_1", "Branch_2", "Branch_3"]) {

        // Define and add to stages dict/map of parallel branch stages
        branchedStages["${STAGE_NAME}"] = {
            stage("Parallel Branch Stage: ${STAGE_NAME}") {
                // Parallel stage work here
                sh "sleep 10"
            }
        }

    }

    // Execute the stages in parallel
    parallel branchedStages
}

stage("Some Other Stage") {
    // Other stuff ...
}

请注意花括号。这将导致以下结果(使用BlueOcean Jenkins插件):

eeq64g8w

eeq64g8w5#

我还尝试了类似的步骤来执行并行阶段并在阶段视图中显示所有阶段。您应该在并行步骤中编写一个阶段,如以下代码块所示。

// Jenkinsfile (Scripted Pipeline)

stage('Build') {
    /* .. Your code/scripts .. */
}

stage('Test') {
    parallel 'linux': {
        stage('Linux') {
            /* .. Your code/scripts .. */
        }
    }, 'windows': {
        stage('Windows') {
            /* .. Your code/scripts .. */
        }
    }
}
flvtvl50

flvtvl506#

上面的例子是错误的,因为变量STAGE_NAME每次都会被覆盖,我和黄伟遇到了同样的问题。
在此找到解决方案:
https://www.convalesco.org/notes/2020/05/26/parallel-stages-in-jenkins-scripted-pipelines.html

def branchedStages = [:]
def STAGE_NAMES =  ["Branch_1", "Branch_2", "Branch_3"]
STAGE_NAMES.each { STAGE_NAME ->
 // Define and add to stages dict/map of parallel branch stages
    branchedStages["${STAGE_NAME}"] = {
        stage("Parallel Branch Stage: ${STAGE_NAME}") {
        // Parallel stage work here
            sh "sleep 10"
        }
    }
  }
parallel branchedStages
kmbjn2e3

kmbjn2e37#

在三个阶段是平行的情况下,我使用了如下所示的方法。

def testCases() {
  stage('Test Cases') {
    def stages = [:]    // declaring empty list
      stages['Unit Testing'] = {
      sh "echo Unit Testing completed"
      }
      stages['Integration Testing'] = {
        sh "echo Integration Testing completed"
      }
      stages['Function Testing'] = {
        sh "echo Function Testing completed"
      }
    parallel(stages) // declaring parallel stages
  }
}
ddarikpa

ddarikpa8#

我已经在并行块中多次使用stage{}。然后每个阶段都显示在阶段视图中。包含parallel的父阶段不包括所有并行阶段的时间,但每个并行阶段都显示在阶段视图中。
在蓝海中,并行阶段单独出现,而不是显示阶段。如果有父阶段,则显示为并行阶段的父阶段。
如果你没有同样的经验,也许是由于插件升级。

相关问题