【问题标题】:Jenkins Pipeline stage starts too soonJenkins 流水线阶段开始得太早
【发布时间】:2017-03-27 06:44:32
【问题描述】:

我的管道有问题。 (Jenkins 版本 1.165.1)

我有:

  • 3 个客户端:('AAA'、'BBB' 和 'CCC')。
  • 2 个参数化构建作业:('Deploy_PrepDB_SHELL' 和 'Deploy_TargetDB_SHELL')

管道(下面列出的由 2 个阶段组成,一个用于每个参数化构建。 每个参数化构建运行 3 次,每个客户端运行一次。 在每个阶段内,3 个客户端可以并行运行。

但是,我希望 Stage #2 仅在 Stage #1 的所有 3 个构建完成并成功完成后运行。 我的问题是,一旦阶段 #1 的所有构建开始,阶段 #2 就会开始。

第 2 阶段不考虑这些构建的最终状态... 因此,Stage #2 开始,而 Stage #1 的构建正在进行中,它会导致错误。

FWIW,使用带有硬编码客户端值的构建实际上解决了这个问题。但我需要使用参数化构建。 我们有超过 3 个客户和 2 个构建工作。硬编码的构建会导致构建数量激增。

如何让 Stage #2(在管道中)了解 Stage #1 的构建结果?并且只有在第 1 阶段的构建成功后才能继续?

我正在考虑的解决方案包括在参数化构建中使用前置操作和后置操作来读取/写入数据库表的状态。 但这感觉很笨拙,我认为 Jenkins 可能有某种更简单的机制来处理这种情况。

你们中的任何人都能够实现这样的东西吗?

谢谢

/* Jenkins Pipeline in Groovy */

def clientlist = ['AAA', 'BBB', 'CCC']


/*
    Stage #1
*/

stage concurrency: 3, name: '1. Deploying Prep Database'
    echo 'Deploying Prep Database DacPac'

    for(item in clientlist)         
    {             
        build job: 'Deploy_PrepDB_SHELL', parameters: [[$class: 'StringParameterValue', name: 'CLIENT_NAME', value: item]], wait: false       
        Thread.sleep(1000)           
    }


/*
    Stage #2
    Should not start until all 3 builds from previous stage have successfully finished!
*/

stage concurrency: 3, name: '2. Deploying Target Database'
    echo 'Deploying Target Database DacPac'            

    for(item in clientlist)      
    {         
        build job: 'Deploy_TargetDB_SHELL', parameters: [[$class: 'StringParameterValue', name: 'CLIENT_NAME', value: item]], wait: false       
        Thread.sleep(1000)      
    }

【问题讨论】:

  • 您是否尝试过将wait 参数设置为true,以便在传递到下一阶段之前等待作业输出?不确定它是否可以与并发一起使用......
  • 我从未将其设置为 true,但我已将其删除。你是对的,它并不真正适用于并发。 IIRC,for循环中的每次迭代都等到前一次完成。

标签: jenkins jenkins-pipeline stage parameterized


【解决方案1】:

我不确定您的管道示例的语法是否正确 - 看起来您在每个 stage 之后都缺少花括号。此外,stage 的当前语法没有 concurrency 选项(我知道。

您需要的是parallel 步骤,而不是concurrency,并在您的build 调用中使用wait: true(默认)。

/* Jenkins Pipeline in Groovy */

def clientlist = ['AAA', 'BBB', 'CCC']

def deployPrep = [:]
def deployTarget = [:]

// Create a map of name-closure pairs
for(item in clientlist)         
{
    // Closures will be executed later by "parallel" step later in pipeline
    deployPrep[item] = {
        // "wait: true" is the default           
        build job: 'Deploy_PrepDB_SHELL',
            parameters: [[$class: 'StringParameterValue', name: 'CLIENT_NAME', value: item]]      
        // Probably don't need this sleep, but including for parity
        Thread.sleep(1000)
    }

    // We can build up multiple maps using one loop.
    // Closures will be executed later by "parallel" step later in pipeline
    deployTarget[item] = {
        build job: 'Deploy_TargetDB_SHELL', 
            parameters: [[$class: 'StringParameterValue', name: 'CLIENT_NAME', value: item]]      
        Thread.sleep(1000)
    }
}

/*
    Stage #1
*/

stage ('1. Deploying Prep Database') {
    echo 'Deploying Prep Database DacPac'
    parallel deployPrep
}

/*
    Stage #2
    Will not start until all 3 builds from previous stage have successfully finished!
*/

stage ('2. Deploying Target Database') {
    echo 'Deploying Target Database DacPac'
    parallel deployTarget
}

【讨论】:

  • 作业目前是硬编码的,我们正在使用并行语法。当我第一次创建这个“shell”管道时,我尝试使用并行语法,但无法让它工作......我认为我们在任何阶段都没有使用大括号。而且并发设置似乎确实允许我们并行处理。请记住,我们使用的是 Jenkins 1.165.1(似乎 Jenkins 2.x 的管道设置可能略有不同)....不过,我会尝试您的解决方案,并让您知道会发生什么。非常感谢!
猜你喜欢
  • 2020-11-07
  • 1970-01-01
  • 2019-02-19
  • 2023-03-07
  • 1970-01-01
  • 2022-10-25
  • 1970-01-01
  • 2018-11-08
  • 2017-03-07
相关资源
最近更新 更多