首页 > 解决方案 > 具有并行和不同容器的 Jenkins 管道

问题描述

所以我已经在运行基于以下示例的 Jenkins 管道:Is it possible to create parallel Jenkins Declarative Pipeline stage in a loop?

我想在不同的隔离容器中运行每个作业,代理名称应该对所有人都相同。尝试了一些选项,所有这些选项都以错误告终,我想我需要同时使用声明性和脚本化但不知道如何。我累的事情:

def generateTerraformStage(env) {
    return {
        agent { label 'local_terraform' }
        stage("stage: Terraform ${TERRAFORM_ACTION} ${env}") {
                echo "${env}"
                sleep 30
        }
    }
} 
stage('parallel stages') {
    agent { label 'local_terraform' }
    steps {
        script {
            parallel parallelStagesMapEnvironment
        }
    }
}

我在测试过程中遇到的错误之一:

"java.lang.NoSuchMethodError: No such DSL method 'agent' found among steps" and "java.lang.IllegalArgumentException: Expected named arguments but got org.jenkinsci.plugins.workflow.cps.CpsClosure2@560f3533"

标签: jenkins-pipelinejenkins-groovyjenkins-job-dsl

解决方案


动态并行阶段只能通过使用脚本管道来创建。API 内置的声明式管道不可用(如agentoptionswhen)。

我没有看到您真正需要动态阶段的任何信息(例如,基于 3rd 方服务返回的值),所以我准备了两个解决方案:

  • 动态并行阶段 - 阶段是基于某些东西生成的
  • 静态并行阶段 - 您知道所有阶段(该when块可用于禁用这些不需要的阶段 - 例如传入参数)
pipeline {
  // ...
  stages {
    stage('dynamic parallel stages') {
      steps {
        script {
           // params.ENVS == ['envA', 'envB', 'envC']
           def values = params.ENVS.split(',')
           def stages = [:]
           for (def value in values) {
             stages[value] = generateTerraformStage(value)
           }
           parallel stages
        }
      }
    }
    stage('static parallel stages') {
      parallel {
        stage('envA') {
          agent { label 'local_terraform' }
          when {
            expression { return params.ENVS.split(',').contains('envA') }
          }
          steps {
            terraformStageLogic 'envA'
          }
        }
        stage('envB') {
          agent { label 'local_terraform' }
          when {
            expression { return params.ENVS.split(',').contains('envB') }
          }
          steps {
            terraformStageLogic 'envB'
          }
        }
        stage('envC') {
          agent { label 'local_terraform' }
          when {
            expression { return params.ENVS.split(',').contains('envC') }
          }
          steps {
            terraformStageLogic 'envC'
          }
        }
        // ...
      }
    }
  }
}

Closure<Void> generateTerraformStage(env) {
  return {
    node('local_terraform') {
      stage("stage: Terraform ${TERRAFORM_ACTION} ${env}") {
        echo "${env}"
        sleep 30
      }
    }
  }
}

void terraformStageLogic(env) {
  echo "${env}"
  sleep 30
}

当您不使用负责生成或执行其他阶段(dynamic parallel stagesstatic parallel stages)的阶段中的工作区时,您不需要为其分配任何节点(浪费资源)。


推荐阅读