我正在将现有的构建管道重建为jenkins声明管道(多分支管道),并且在处理构建传播时遇到问题。
打包并存储所有相关文件后,管道应该等待用户输入以触发部署。
如果我只是添加一个输入步骤,则阻止当前的构建节点。由于这个执行器很重,我想将这一步移到更轻量级的机器上。
最初我作为脚本管道完成了工作,只创建了两个不同的node('label')
块。有没有办法让我用声明性语法做类似的事情?
node('spine') {
stage('builder') {
sh 'mvn clean compile'
stash name: 'artifact', includes: 'target/*.war'
}
}
node('lightweight') {
stage('wait') {
timeout(time:5, unit:'DAYS') {
input message:'Approve deployment?'
}
}
// add deployment stages
}
我已经尝试了几件事:
在顶层配置代理并将其他代理配置添加到传播步骤,但随后我有两个执行器阻塞,因为顶级定义的构建节点未停止。
在顶层设置agent none
并在每个步骤配置代理。然后第一个节点上没有git checkout。
编辑1
我根据你的建议重新配置了我的管道,它目前看起来像这样:
pipeline {
agent none
tools {
maven 'M3'
}
stages {
stage('Build') {
agent { label 'spine' }
steps {
checkout scm // needed, otherwise the workspace on the first step is empty
sh "mvn clean compile"
}
}
stage('Test') {
agent { label 'spine' }
steps {
sh "mvn verify" // fails because the workspace is empty aggain
junit '**/target/surefire-reports/TEST-*.xml'
}
}
}
}
此构建将失败,因为工作区不会在步骤之间进行,因为它们不会在同一个执行程序上运行。
编辑2
显然,有时候步骤会在同一个执行器上运行,有时却不会。 (我们根据需要在我们的mesos / dcos集群上生成构建从属,因此更改执行者中间构建将是一个问题)只要代理定义中的标签不变,我希望jenkins只运行当前的执行程序。
答案 0 :(得分:28)
请参阅best practice 7:不要:在节点块中使用输入。在声明性管道中,节点选择是通过agent
指令完成的。
文档here描述了如何为pipline定义none
,然后使用阶段级agent
指令在所需节点上运行阶段。我也尝试了相反的方法(在某个节点上定义一个全局代理,然后在阶段级别为输入定义none
),但这不起作用。如果管道分配了从属设备,则无法释放一个或多个特定阶段的从属设备。
这是our pipeline:
的结构pipeline {
agent none
stages {
stage('Build') {
agent { label 'yona' }
steps {
...
}
}
stage('Decide tag on Docker Hub') {
agent none
steps {
script {
env.TAG_ON_DOCKER_HUB = input message: 'User input required',
parameters: [choice(name: 'Tag on Docker Hub', choices: 'no\nyes', description: 'Choose "yes" if you want to deploy this build')]
}
}
}
stage('Tag on Docker Hub') {
agent { label 'yona' }
when {
environment name: 'TAG_ON_DOCKER_HUB', value: 'yes'
}
steps {
...
}
}
}
}
通常,构建阶段在标记为“yona”的构建从属上执行,但输入阶段在主服务器上运行。
答案 1 :(得分:3)
另一种方法是使用表达式指令和beforeAgent,它跳过“决定”步骤并避免弄乱“ env”全局变量:
pipeline {
agent none
stages {
stage('Tag on Docker Hub') {
when {
expression {
input message: 'Tag on Docker Hub?'
// if input is Aborted, the whole build will fail, otherwise
// we must return true to continue
return true
}
beforeAgent true
}
agent { label 'yona' }
steps {
...
}
}
}
}
答案 2 :(得分:1)
在顶部使用agent none,并为包括输入步骤在内的每个阶段定义代理。
来源:Use a lightweight executor for a declarative pipeline stage (agent none)
中的讨论更新:“第一个节点上没有git checkout”是什么意思?请展示你到目前为止的声明性管道。
答案 3 :(得分:0)
我知道此线程很旧,但是我认为解决“ Edit 2”问题的方法除了隐藏外,还可以使用嵌套阶段。
根据此页面:
...如果您在管道中使用多个代理,但是要确保使用同一代理的阶段使用相同的工作空间,则可以使用带有代理指令的父阶段,然后使用它的stage指令中的stage将在同一工作区中的同一执行程序上运行。
以下是提供的示例:
pipeline {
agent none
stages {
stage("build and test the project") {
agent {
docker "our-build-tools-image"
}
stages {
stage("build") {
steps {
sh "./build.sh"
}
}
stage("test") {
steps {
sh "./test.sh"
}
}
}
post {
success {
stash name: "artifacts", includes: "artifacts/**/*"
}
}
}
stage("deploy the artifacts if a user confirms") {
input {
message "Should we deploy the project?"
}
agent {
docker "our-deploy-tools-image"
}
steps {
sh "./deploy.sh"
}
}
}
}
答案 4 :(得分:0)
OP的问题是如何“在不阻塞...的情况下等待声明性管道中的用户输入”。这似乎不可能。尝试使用代理:没有人不会在声明性管道中释放构建执行器 。
此:
pipeline {
agent none
stages {
stage('Build') {
agent { label 'big-boi' }
steps {
echo 'Stubbed'
}
}
stage('Prompt for deploy') {
agent { label 'tiny' }
steps {
input 'Deploy this?'
}
}
stage('Deploy') {
agent { label 'big-boi' }
steps {
echo "Deploying"
build job: 'deploy-to-higher-environment'
}
}
}
}
...运行时,看起来像这样:
...以及这个: