Jenkins 管道可以有可选的输入步骤吗? [英] Can a Jenkins pipeline have an optional input step?

查看:14
本文介绍了Jenkins 管道可以有可选的输入步骤吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以创建带有可选输入阶段的 Jenkins 管道?

Is it possible to create a Jenkins pipeline with an optional input stage?

下面的代码段没有达到这个目标.

The below snippet doesn't achieve this goal.

阶段(以及因此的输入提示)应该只针对特定分支运行.

The stage (and therefore the input prompt) should only run for specific branches.

此阶段适用于所有分支.使用输入步骤时忽略 when 过滤器.

This stage runs for all branches. The when filter is ignored when an input step is used.

stage('Approve') {
            when {
                expression { BRANCH_NAME ==~ /^qa[w-_]*$/ }
            }
            input {
                message "Approve release?"
                ok "y"
                submitter "admin"
                parameters {
                    string(name: 'IS_APPROVED', defaultValue: 'y', description: 'Deploy to master?')
                }
            }
            steps {
                script {
                    if (IS_APPROVED != 'y') {
                        currentBuild.result = "ABORTED"
                        error "User cancelled"
                    }
                }
            }
        }

推荐答案

过滤器不会被忽略,它只是在输入步骤之后进行评估.在您的示例中,始终会询问您是否部署,如果您不在 QA 分支上,则不会发生任何事情.

The filter is not ignored, it is just evaluated after the input step. In your example, you would always be asked whether to deploy, and in the case that you are not on a QA branch, nothing would happen.

现在您可能会问,为什么 Jenkins 不首先评估 'when' 指令.在这种情况下,您不能在 when 条件中使用输入参数.

Now you could ask why Jenkins isn't evaluating the 'when' directive first. In that case, you could not use the input parameter in your when condition.

拥有多个 when 指令就像在声明性管道中编写脚本一样.

And having multiple when directives would be like scripting within the declarative pipeline.

但是,有一个表达式允许您控制何时评估when"指令.这是 beforeAgent.它允许您在分配代理之前评估 when 语句.与此类似,您需要类似 beforeInput 的东西.您可以为此创建一个功能请求.

However, there is an expression that allows you controlling when the 'when' directive is evaluated. This is beforeAgent. It allows you to evaluate the when statement before the agent is allocated. Similar to that, you would need something like beforeInput. You could create a feature request for that.

我不再使用输入指令,现在我在脚本块中使用输入,因为这提供了更大的灵活性,例如当有人必须批准某事时,我会发送 Slack 通知,而这在声明性方法中是不可能的.你需要一个通知指令.如果有的话,是在输入步骤之前还是之后评估?

I stepped away from using the input directive and I use input within a scripting block now, because that provides much more flexibility, e.g. I am sending Slack notifications when somebody has to approve something, which is impossible with the declarative approach. You would need a notify directive for that. And if there was one, is that going to be evaluated before or after the input step?

您会发现,以声明方式做所有事情并不总是最好的方式.所以我推荐的方法如下(免责声明:这是未经测试的!):

You see, doing everything declarative is not always the best way. So my recommended approach is the following (disclaimer: this is untested!):

pipeline {
  // We want to use agents per stage to avoid blocking our build agents
  // while we are waiting for user input.
  agent none
  ...
  // The question mark naming convention is helpful to show you which
  //  approval stage belongs to which work stage.
  stage('Release?') {
    // Don't allocate an agent because we don't want to block our
    // slaves while waiting for user input.
    agent none
    when {
      // You forgot the 'env.' in your example above ;)
      expression { env.BRANCH_NAME ==~ /^qa[w-_]*$/ }
    }
    options {
      // Optionally, let's add a timeout that we don't allow ancient
      // builds to be released.
      timeout time: 14, unit: 'DAYS' 
    }
    steps {
      // Optionally, send some notifications to the approver before
      // asking for input. You can't do that with the input directive
      // without using an extra stage.
      slackSend ...

      // The input statement has to go to a script block because we
      // want to assign the result to an environment variable. As we 
      // want to stay as declarative as possible, we put noting but
      // this into the script block.
      script {
        // Assign the 'DO_RELEASE' environment variable that is going
        //  to be used in the next stage.
        env.DO_RELEASE = input ...
      }
      // In case you approved multiple pipeline runs in parallel, this
      // milestone would kill the older runs and prevent deploying
      // older releases over newer ones.
      milestone 1
    }
  }
  stage('Release') {
    // We need a real agent, because we want to do some real work.
    agent any
    when {
      // Evaluate the 'when' directive before allocating the agent.
      beforeAgent true
      // Only execute the step when the release has been approved.
      environment name: 'DO_RELEASE', value: 'yes'
    }
    steps {
      // Make sure that only one release can happen at a time.
      lock('release') {
        // As using the first milestone only would introduce a race 
        // condition (assume that the older build would enter the 
        // milestone first, but the lock second) and Jenkins does
        // not support inter-stage locks yet, we need a second 
        // milestone to make sure that older builds don't overwrite
        // newer ones.
        milestone 2

        // Now do the actual work here.
        ...
      }
    }
  }

这篇关于Jenkins 管道可以有可选的输入步骤吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆