在 Jenkins 中从管道中止当前构建
Posted
技术标签:
【中文标题】在 Jenkins 中从管道中止当前构建【英文标题】:Abort current build from pipeline in Jenkins 【发布时间】:2017-07-28 19:12:48 【问题描述】:我有一个包含多个阶段的 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
变量可用,但我找不到它的文档。
【问题讨论】:
【参考方案1】:您可以将构建标记为 ABORTED,然后使用error
步骤使构建停止:
if (!continueBuild)
currentBuild.result = 'ABORTED'
error('Stopping early…')
在阶段视图中,这将显示构建在此阶段停止,但整个构建将被标记为中止,而不是失败(请参阅构建 #9 的灰色图标):
【讨论】:
太棒了。有没有办法提前成功退出? 抱歉,已经找到。只需返回node-level
而不是 stage-level
即可使管道提前成功退出。
if (!continueBuild)...我们如何设置“ContinueBuild”值?
@NishantKansal 这只是原始发帖人提到的变量名。语法为def continueBuild = false
(或true
),但由您决定何时要中止构建,例如通过调用方法def continueBuild = makeSomeDecision()
。
仅供参考,hudson/model/Result.java【参考方案2】:
经过一些测试,我想出了以下解决方案:
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
这将导致以下阶段视图:
失败阶段
如果你不喜欢失败的阶段,你必须使用返回。但请注意,您必须跳过每个阶段或包装器。
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
【讨论】:
我需要更清楚一点:如果(您的条件)...我有一个与先前和当前提交 id 匹配的 shell 脚本来决定构建是应该继续还是停止。是不是我必须将该 shell 脚本的退出状态传递给 if(您的条件)?如果是,那么如何?请帮忙。【参考方案3】:按照来自 Jenkins 的 documentation,您应该能够生成错误以停止构建并像这样设置构建结果:
currentBuild.result = 'ABORTED'
希望对您有所帮助。
【讨论】:
我刚试过这个,之后有一个回声,它并没有阻止管道的其余部分运行。 该命令只设置构建结果。要停止管道,您必须生成信号错误:error('error message')
或 throw new Exception()
仅当您想查看堆栈跟踪时才使用throw new Exception()
。【参考方案4】:
我以声明方式处理如下:
基于 catchError 块,它将执行 post 块。 如果发布结果属于失败类别,则会执行错误块以停止即将到来的阶段,如生产、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'
【讨论】:
我不知道您的设置,但是授予 sudo bash 任何权限都不是很安全。更好的是,只对您需要的脚本授予 sudo 权限,并在之前仔细检查它。【参考方案5】:受到所有答案的启发,我将所有内容整合到一个脚本化管道中。请记住,这不是声明式管道。
要让这个例子正常工作,你需要:
QuickFIX 形成这个答案Jenkins CI Pipeline Scripts not permitted to use method groovy.lang.GroovyObject discord 通知插件 - https://plugins.jenkins.io/discord-notifier/ 代码填写的Discord频道webhook url我的想法是如果管道是“重播”而不是由“运行按钮”启动(在 Jenskins BlueOcean 的分支选项卡中),则中止管道:
def isBuildAReplay()
// https://***.com/questions/51555910/how-to-know-inside-jenkinsfile-script-that-current-build-is-an-replay/52302879#52302879
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
【讨论】:
【参考方案6】:我们使用的是:
try
input 'Do you want to abort?'
catch (Exception err)
currentBuild.result = 'ABORTED';
return;
最后的“return”确保不再执行任何代码。
【讨论】:
【参考方案7】:您可以转到 Jenkins 的脚本控制台并运行以下命令来中止挂起/任何 Jenkins 作业的构建/运行:
Jenkins .instance.getItemByFullName("JobName")
.getBuildByNumber(JobNumber)
.finish(hudson.model.Result.ABORTED, new java.io.IOException("Aborting build"));
【讨论】:
以上是关于在 Jenkins 中从管道中止当前构建的主要内容,如果未能解决你的问题,请参考以下文章