从 Jenkins 中的管道中止当前构建
Abort current build from pipeline in Jenkins
我有一个 Jenkins 管道,它有多个阶段,例如:
node("nodename") {
stage("Checkout") {
git ....
}
stage("Check Preconditions") {
...
if(!continueBuild) {
// What do I put here? currentBuild.xxx ?
}
}
stage("Do a lot of work") {
....
}
}
如果不满足某些先决条件并且没有实际工作要做,我希望能够取消(而不是失败)构建。我怎样才能做到这一点?我知道 currentBuild
变量可用,但我找不到它的文档。
按照 Jenkins 的 documentation,您应该能够生成错误以停止构建并设置构建结果,如下所示:
currentBuild.result = 'ABORTED'
希望对您有所帮助。
您可以将构建标记为 ABORTED,然后使用 error
步骤使构建停止:
if (!continueBuild) {
currentBuild.result = 'ABORTED'
error('Stopping early…')
}
在 Stage View 中,这将显示构建在此阶段停止,但整个构建将被标记为中止,而不是失败(参见构建 #9 的灰色图标):
经过一些测试,我想出了以下解决方案:
def autoCancelled = false
try {
stage('checkout') {
...
if (your condition) {
autoCancelled = true
error('Aborting the build to prevent a loop.')
}
}
} catch (e) {
if (autoCancelled) {
currentBuild.result = 'ABORTED'
echo('Skipping mail notification')
// return here instead of throwing error to keep the build "green"
return
}
// normal error handling
throw e
}
这将导致以下阶段视图:
阶段失败
如果你不喜欢失败的阶段,你必须使用return。但请注意,您必须跳过每个阶段或包装器。
def autoCancelled = false
try {
stage('checkout') {
...
if (your condition) {
autoCancelled = true
return
}
}
if (autoCancelled) {
error('Aborting the build to prevent a loop.')
// return would be also possible but you have to be sure to quit all stages and wrapper properly
// return
}
} catch (e) {
if (autoCancelled) {
currentBuild.result = 'ABORTED'
echo('Skipping mail notification')
// return here instead of throwing error to keep the build "green"
return
}
// normal error handling
throw e
}
结果:
自定义错误作为指标
您也可以使用自定义消息代替局部变量:
final autoCancelledError = 'autoCancelled'
try {
stage('checkout') {
...
if (your condition) {
echo('Aborting the build to prevent a loop.')
error(autoCancelledError)
}
}
} catch (e) {
if (e.message == autoCancelledError) {
currentBuild.result = 'ABORTED'
echo('Skipping mail notification')
// return here instead of throwing error to keep the build "green"
return
}
// normal error handling
throw e
}
我们用的东西是:
try {
input 'Do you want to abort?'
} catch (Exception err) {
currentBuild.result = 'ABORTED';
return;
}
末尾的 "return" 确保不再执行其他代码。
我用如下所示的声明方式处理:
基于 catchError 块,它将执行 post 块。
如果 post 结果属于失败类别,将执行错误块以停止后续阶段,如 Production、PreProd 等
pipeline {
agent any
stages {
stage('Build') {
steps {
catchError {
sh '/bin/bash path/To/Filename.sh'
}
}
post {
success {
echo 'Build stage successful'
}
failure {
echo 'Compile stage failed'
error('Build is aborted due to failure of build stage')
}
}
}
stage('Production') {
steps {
sh '/bin/bash path/To/Filename.sh'
}
}
}
}
您可以转到 Jenkins 的脚本控制台和 运行 以下命令来中止挂起的/任何 Jenkins 作业 build/run:
Jenkins .instance.getItemByFullName("JobName")
.getBuildByNumber(JobNumber)
.finish(hudson.model.Result.ABORTED, new java.io.IOException("Aborting build"));
受所有答案的启发,我将所有内容整合到一个脚本化管道中。请记住,这不是声明式管道。
要使此示例正常运行,您需要:
- QuickFIX 形成这个答案
- discord 通知插件 - https://plugins.jenkins.io/discord-notifier/
- Discord 频道 webhook url 填写代码
我的想法是,如果管道是 "replayed" vs 由 "run button" 启动(在 Jenskins BlueOcean 的分支选项卡中):
def isBuildAReplay() {
//
def replyClassName = "org.jenkinsci.plugins.workflow.cps.replay.ReplayCause"
currentBuild.rawBuild.getCauses().any{ cause -> cause.toString().contains(replyClassName) }
}
node {
try {
stage('check replay') {
if (isBuildAReplay()) {
currentBuild.result = 'ABORTED'
error 'Biuld REPLAYED going to EXIT (please use RUN button)'
} else {
echo 'NOT replay'
}
}
stage('simple stage') {
echo 'hello from simple stage'
}
stage('error stage') {
//error 'hello from simple error'
}
stage('unstable stage') {
unstable 'hello from simple unstable'
}
stage('Notify sucess') {
//Handle SUCCESS|UNSTABLE
discordSend(description: "${currentBuild.currentResult}: Job ${env.JOB_NAME} \nBuild: ${env.BUILD_NUMBER} \nMore info at: \n${env.BUILD_URL}", footer: 'No-Code', unstable: true, link: env.BUILD_URL, result: "${currentBuild.currentResult}", title: "${JOB_NAME} << CLICK", webhookURL: 'https://discordapp.com/api/webhooks/')
}
} catch (e) {
echo 'This will run only if failed'
if(currentBuild.result == 'ABORTED'){
//Handle ABORTED
discordSend(description: "${currentBuild.currentResult}: Job ${env.JOB_NAME} \nBuild: ${env.BUILD_NUMBER} \nMore info at: \n${env.BUILD_URL}\n\nERROR.toString():\n"+e.toString()+"\nERROR.printStackTrace():\n"+e.printStackTrace()+" ", footer: 'No-Code', unstable: true, link: env.BUILD_URL, result: "ABORTED", title: "${JOB_NAME} << CLICK", webhookURL: 'https://discordapp.com/api/webhooks/')
throw e
}else{
//Handle FAILURE
discordSend(description: "${currentBuild.currentResult}: Job ${env.JOB_NAME} \nBuild: ${env.BUILD_NUMBER} \nMore info at: \n${env.BUILD_URL}\n\nERROR.toString():\n"+e.toString()+"\nERROR.printStackTrace():\n"+e.printStackTrace()+" ", footer: 'No-Code', link: env.BUILD_URL, result: "FAILURE", title: "${JOB_NAME} << CLICK", webhookURL: 'https://discordapp.com/api/webhooks/')
throw e
}
} finally {
echo 'I will always say Hello again!'
}
}
主要技巧是实现中止状态的行顺序:
currentBuild.result = 'ABORTED'
error 'Biuld REPLAYED going to EXIT (please use RUN button)'
先设置状态再抛出异常
在 catch 块中都有效:
currentBuild.result
currentBuild.currentResult
我有一个 Jenkins 管道,它有多个阶段,例如:
node("nodename") {
stage("Checkout") {
git ....
}
stage("Check Preconditions") {
...
if(!continueBuild) {
// What do I put here? currentBuild.xxx ?
}
}
stage("Do a lot of work") {
....
}
}
如果不满足某些先决条件并且没有实际工作要做,我希望能够取消(而不是失败)构建。我怎样才能做到这一点?我知道 currentBuild
变量可用,但我找不到它的文档。
按照 Jenkins 的 documentation,您应该能够生成错误以停止构建并设置构建结果,如下所示:
currentBuild.result = 'ABORTED'
希望对您有所帮助。
您可以将构建标记为 ABORTED,然后使用 error
步骤使构建停止:
if (!continueBuild) {
currentBuild.result = 'ABORTED'
error('Stopping early…')
}
在 Stage View 中,这将显示构建在此阶段停止,但整个构建将被标记为中止,而不是失败(参见构建 #9 的灰色图标):
经过一些测试,我想出了以下解决方案:
def autoCancelled = false
try {
stage('checkout') {
...
if (your condition) {
autoCancelled = true
error('Aborting the build to prevent a loop.')
}
}
} catch (e) {
if (autoCancelled) {
currentBuild.result = 'ABORTED'
echo('Skipping mail notification')
// return here instead of throwing error to keep the build "green"
return
}
// normal error handling
throw e
}
这将导致以下阶段视图:
阶段失败
如果你不喜欢失败的阶段,你必须使用return。但请注意,您必须跳过每个阶段或包装器。
def autoCancelled = false
try {
stage('checkout') {
...
if (your condition) {
autoCancelled = true
return
}
}
if (autoCancelled) {
error('Aborting the build to prevent a loop.')
// return would be also possible but you have to be sure to quit all stages and wrapper properly
// return
}
} catch (e) {
if (autoCancelled) {
currentBuild.result = 'ABORTED'
echo('Skipping mail notification')
// return here instead of throwing error to keep the build "green"
return
}
// normal error handling
throw e
}
结果:
自定义错误作为指标
您也可以使用自定义消息代替局部变量:
final autoCancelledError = 'autoCancelled'
try {
stage('checkout') {
...
if (your condition) {
echo('Aborting the build to prevent a loop.')
error(autoCancelledError)
}
}
} catch (e) {
if (e.message == autoCancelledError) {
currentBuild.result = 'ABORTED'
echo('Skipping mail notification')
// return here instead of throwing error to keep the build "green"
return
}
// normal error handling
throw e
}
我们用的东西是:
try {
input 'Do you want to abort?'
} catch (Exception err) {
currentBuild.result = 'ABORTED';
return;
}
末尾的 "return" 确保不再执行其他代码。
我用如下所示的声明方式处理:
基于 catchError 块,它将执行 post 块。 如果 post 结果属于失败类别,将执行错误块以停止后续阶段,如 Production、PreProd 等
pipeline {
agent any
stages {
stage('Build') {
steps {
catchError {
sh '/bin/bash path/To/Filename.sh'
}
}
post {
success {
echo 'Build stage successful'
}
failure {
echo 'Compile stage failed'
error('Build is aborted due to failure of build stage')
}
}
}
stage('Production') {
steps {
sh '/bin/bash path/To/Filename.sh'
}
}
}
}
您可以转到 Jenkins 的脚本控制台和 运行 以下命令来中止挂起的/任何 Jenkins 作业 build/run:
Jenkins .instance.getItemByFullName("JobName")
.getBuildByNumber(JobNumber)
.finish(hudson.model.Result.ABORTED, new java.io.IOException("Aborting build"));
受所有答案的启发,我将所有内容整合到一个脚本化管道中。请记住,这不是声明式管道。
要使此示例正常运行,您需要:
- QuickFIX 形成这个答案
- discord 通知插件 - https://plugins.jenkins.io/discord-notifier/
- Discord 频道 webhook url 填写代码
我的想法是,如果管道是 "replayed" vs 由 "run button" 启动(在 Jenskins BlueOcean 的分支选项卡中):
def isBuildAReplay() {
//
def replyClassName = "org.jenkinsci.plugins.workflow.cps.replay.ReplayCause"
currentBuild.rawBuild.getCauses().any{ cause -> cause.toString().contains(replyClassName) }
}
node {
try {
stage('check replay') {
if (isBuildAReplay()) {
currentBuild.result = 'ABORTED'
error 'Biuld REPLAYED going to EXIT (please use RUN button)'
} else {
echo 'NOT replay'
}
}
stage('simple stage') {
echo 'hello from simple stage'
}
stage('error stage') {
//error 'hello from simple error'
}
stage('unstable stage') {
unstable 'hello from simple unstable'
}
stage('Notify sucess') {
//Handle SUCCESS|UNSTABLE
discordSend(description: "${currentBuild.currentResult}: Job ${env.JOB_NAME} \nBuild: ${env.BUILD_NUMBER} \nMore info at: \n${env.BUILD_URL}", footer: 'No-Code', unstable: true, link: env.BUILD_URL, result: "${currentBuild.currentResult}", title: "${JOB_NAME} << CLICK", webhookURL: 'https://discordapp.com/api/webhooks/')
}
} catch (e) {
echo 'This will run only if failed'
if(currentBuild.result == 'ABORTED'){
//Handle ABORTED
discordSend(description: "${currentBuild.currentResult}: Job ${env.JOB_NAME} \nBuild: ${env.BUILD_NUMBER} \nMore info at: \n${env.BUILD_URL}\n\nERROR.toString():\n"+e.toString()+"\nERROR.printStackTrace():\n"+e.printStackTrace()+" ", footer: 'No-Code', unstable: true, link: env.BUILD_URL, result: "ABORTED", title: "${JOB_NAME} << CLICK", webhookURL: 'https://discordapp.com/api/webhooks/')
throw e
}else{
//Handle FAILURE
discordSend(description: "${currentBuild.currentResult}: Job ${env.JOB_NAME} \nBuild: ${env.BUILD_NUMBER} \nMore info at: \n${env.BUILD_URL}\n\nERROR.toString():\n"+e.toString()+"\nERROR.printStackTrace():\n"+e.printStackTrace()+" ", footer: 'No-Code', link: env.BUILD_URL, result: "FAILURE", title: "${JOB_NAME} << CLICK", webhookURL: 'https://discordapp.com/api/webhooks/')
throw e
}
} finally {
echo 'I will always say Hello again!'
}
}
主要技巧是实现中止状态的行顺序:
currentBuild.result = 'ABORTED'
error 'Biuld REPLAYED going to EXIT (please use RUN button)'
先设置状态再抛出异常
在 catch 块中都有效:
currentBuild.result
currentBuild.currentResult