从 Jenkins 的管道中中止当前构建

问题描述 投票:0回答:11

我有一个具有多个阶段的 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 jenkins-pipeline
11个回答
160
投票

您可以将构建标记为已中止,然后使用

error
步骤使构建停止:

if (!continueBuild) {
    currentBuild.result = 'ABORTED'
    error('Stopping early…')
}

在阶段视图中,这将显示构建在此阶段停止,但构建整体将被标记为中止,而不是失败(请参阅构建 #9 的灰色图标):

Pipeline Stage View


22
投票

经过一些测试,我想出了以下解决方案:

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
}

这将导致以下舞台视图:

enter image description here

失败阶段

如果你不喜欢失败的阶段,你必须使用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
}

结果:

enter image description here

自定义错误作为指示器

您还可以使用自定义消息而不是局部变量:

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
}

7
投票

我发现的最优雅的方式: 注意,它需要在

Manage Jenkins -> In process script approval
页面

批准方法签名
currentBuild.result = "ABORTED"
throw new org.jenkinsci.plugins.workflow.steps.FlowInterruptedException(hudson.model.Result.ABORTED)

enter image description here

如果您只想标记构建/阶段结果但继续下一步和阶段,您可以使用:

steps{
    script{
        echo "Hello"
        catchError(buildResult: 'ABORTED', stageResult: 'ABORTED') {
            error("Your abortion reason goes here")
        }
    }
}

4
投票

如果您能够批准 FlowInterruptedException 的构造函数,那么您可以执行以下操作:

throw new FlowInterruptedException(Result.ABORTED, new UserInterruption(getCurrentUserId()))

您可以将文件添加到共享库存储库中

var/abortError.groovy
:

import org.jenkinsci.plugins.workflow.steps.FlowInterruptedException
import jenkins.model.CauseOfInterruption.UserInterruption

def call(message)
{
    currentBuild.displayName = "#${env.BUILD_NUMBER} $message"
    echo message
    currentBuild.result = 'ABORTED'
    throw new FlowInterruptedException(Result.ABORTED, new UserInterruption(env.BUILD_USER_ID))
}

然后你就可以这样使用它(导入库后):

abortError("some message")

请注意,如果您在控制台日志中看到以下错误:

org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use new org.jenkinsci.plugins.workflow.steps.FlowInterruptedException hudson.model.Result jenkins.model.CauseOfInterruption[]

您需要按照链接表单日志并批准安全例外。


3
投票

按照 Jenkins 的文档,您应该能够生成错误来停止构建并设置构建结果,如下所示:

currentBuild.result = 'ABORTED'

希望有帮助。


3
投票

我们使用的东西是:

try {
 input 'Do you want to abort?'
} catch (Exception err) {
 currentBuild.result = 'ABORTED';
 return;
}

最后的“返回”确保不再执行任何代码。


2
投票

我是用声明式的方式处理的,如下图:

基于 catchError 块,它将执行 post 块。 如果后期结果属于失败类别,则将执行错误块以停止即将到来的阶段,例如生产、预生产等。

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'
      }
    }
  }
}

2
投票

受到所有答案的启发,我将所有内容整合到一个脚本化管道中。请记住,这不是声明式管道。

要使此示例正常工作,您需要:

我的想法是,如果管道是“重播”而不是通过“运行按钮”启动(在 Jenskins BlueOcean 的分支选项卡中),则中止管道:

def isBuildAReplay() {
  // https://stackoverflow.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

1
投票

您可以转到 Jenkins 的脚本控制台并运行以下命令来中止挂起/任何 Jenkins 作业构建/运行:

Jenkins .instance.getItemByFullName("JobName")
        .getBuildByNumber(JobNumber)
        .finish(hudson.model.Result.ABORTED, new java.io.IOException("Aborting build"));

1
投票

Executor.interrupt(Result)
方法是我能找到的最干净、最直接的方法来提前停止构建选择结果。

script {
    currentBuild.getRawBuild().getExecutor().interrupt(Result.NOT_BUILT)
    sleep(1)   // Interrupt is not blocking and does not take effect immediately.
}

您可以为此使用任何 Result 常量,但根据您“取消”的愿望,因为“没有实际工作要做”,我认为 NOT_BUILT 结果是最合适的。这具有向连接的集成(例如 Bitbucket)发出信号的额外优势,即构建应被忽略并且不计为失败。

优点

  • 在声明式管道中与脚本式管道一样工作。
  • 没有 try/catch 或异常需要处理。
  • 在 UI 中将调用阶段和任何后续阶段标记为绿色/通过。

缺点

  • 需要大量进程内脚本批准,其中包括“被认为不安全”的批准。批准并谨慎使用。
  • 摘自我在
devops.stackexchange.com

上的回答。 至于

currentBuild

,请查看

RunWrapper
类的文档。


0
投票
© www.soinside.com 2019 - 2024. All rights reserved.