Jenkins Pipeline: “input” 步骤阻塞执行器

44

在阅读了pipelineJenkinsfile文档后,我有点困惑如何创建一个阶段->生产的流水线。

一种方法是使用 input 步骤,例如:

node() {
  stage 'Build to Stage'
  sh '# ...'

  input 'Deploy to Production'
  stage 'Build to Production'
  sh '# ...'
}

这种方式有些笨重,因为它会一直阻塞执行器,直到你想部署到生产环境。有没有其他方式可以从Jenkins进行部署呢?


我抓住机会将问题标题从“使用Jenkins创建阶段和生产管道”更新为更具描述性的标题。 - StephenKing
3个回答

51

编辑(2016年10月):请参阅下面的其他答案"使用里程碑和锁定",其中包括最近引入的功能。

使用timeout步骤

作为第一种选择,您可以将sh步骤包装到timeout步骤中。

node() {
  stage 'Build to Stage' {
    sh '# ...'
  }

  stage 'Promotion' {
    timeout(time: 1, unit: 'HOURS') {
      input 'Deploy to Production?'
    }
  }

  stage 'Deploy to Production' {
    sh '# ...'
  }
}

这将在超时后停止构建。

input步骤移至轻量级执行器

另一个选项是不为input步骤分配重量级执行器。您可以通过在node块之外使用input步骤来实现这一点,像这样:

stage 'Build to Stage' {
  node {
      sh "echo building"
      stash 'complete-workspace'
  }
}

stage 'Promotion' {
  input 'Deploy to Production?'
}

stage 'Deploy to Production' {
  node {
    unstash 'complete-workspace'
    sh "echo deploying"
  }
}

曾经是 更加优雅的方式,但仍然可以与 timeout 步骤结合使用。

编辑:正如 @amuniz 指出的那样,您必须stash/unstash工作区的内容,因为两个 node 步骤可能分配给不同的节点或工作区目录。


根据@amuniz的描述,您需要包含stash/unstash步骤来复制不同节点/执行器并接管第二个节点块。 - StephenKing
@StephenKing,能否请您解释一下被阻塞的轻量级执行器会消耗哪些资源?我尝试了上面的代码块,但在Web控制台的左侧面板中仍然看到执行器被阻塞。 - Anand Patel
请查看我之前发布的链接轻量级执行器——一个被假定不会占用任何重要计算能力的未计数插槽。 - StephenKing
1
输入能和 when 条件结合使用吗?例如,当分支为'master'时才提示。 - claya

35

鉴于Jenkins管道的最新进展,最好的方法可能是以下方式(来源:jenkins.io/blog):

使用milestonelock

  • lock步骤(来自lockable-resources插件)允许锁定某些指定资源,以便仅有单个管道执行可以同时进入此阶段(您不希望同时运行两个部署,对吗?)
  • milestone步骤(来自pipeline-milestone-step插件)将中止任何旧的管道执行,如果更近期的构建已经到达了里程碑(您不想让CI中悬挂时间更长的旧构建覆盖新构建的部署,对吗?)。
stage('Deploy') {
  input "Deploy?"
  milestone()
  lock('Deployment') {
    node {
      echo "Deploying"
    }
  }
}

部署阶段不限制并发性,但需要用户手动输入。几个构建可能会到达此步骤等待输入。当用户提升特定的构建时,所有先前的构建都将被中止,确保始终部署最新的代码。

我建议阅读整个故事,其中包括更多有用的信息。

感谢@amuniz,他正在维护这些插件。


我认为你需要在输入步骤之前插入一个里程碑步骤。 - rbarni
取决于您想要实现的行为。 - StephenKing
是的,确实是这样。我假设使用情况包括需要在允许新管道进行时中止等待同一输入步骤的旧管道。 - rbarni
7
仅仅使用milestonelock并不能解决OP阻止执行器的问题,对吧?关键似乎仍然是将input步骤定义在node块外。milestonelock只是防止多个构建进入部署操作。 - Gary
请提出一个新问题。 - StephenKing
但需要用户手动输入。你是在说不能使用Jenkins REST API来完成输入步骤吗? - Learner

13

您必须在任何节点块之外使用输入步骤,以便它不保留任何执行程序:

stage 'Build'
node('build-node') {
  sh 'call you build tool'
  stash includes: 'target/my-output-artifact.whatever', name: 'built'
}

input 'Continue to deploy stage?'

stage 'Deploy'
node('deploy-node') {
  unstash 'built'
  sh 'scp target/my-output-artifact.whatever user@deploy-server:/deploy'
}

如果您只想每次部署一个,您可以锁定部署阶段:

lock ('deploy-server') {
  stage 'Deploy'
  node('deploy-node') {
    unstash 'built'
    sh 'scp target/my-output-artifact.whatever user@deploy-server:/deploy'
  }
}

请注意这里的关键部分是stash步骤,因为您可以将工件从一个节点移动到另一个节点(您可以在两个操作之间共享同一节点,但不能保证工作空间在两个节点调用之间不被更改,特别是如果存在等待input的情况)。


10
这在声明式流水线语法中是怎么工作的? - Learner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接