中止Jenkins中管道的当前构建

xv8emn3q  于 2022-11-02  发布在  Jenkins
关注(0)|答案(9)|浏览(373)

我有一个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变量是可用的,但我找不到它的文档。

yjghlzjz

yjghlzjz1#

可以将生成标记为ABORTED,然后使用error步骤使生成停止:

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

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

nbysray5

nbysray52#

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

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。但是要注意你必须跳过每一个阶段或 Package 器。

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

vzgqcmou3#

按照Jenkins提供的文档,您应该能够生成一个错误来停止构建并设置构建结果,如下所示:
currentBuild.result = 'ABORTED'
希望能有所帮助。

yx2lnoni

yx2lnoni4#

我们使用的是:

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

最后的“return”确保不再执行其他代码。

okxuctiv

okxuctiv5#

我以声明方式进行了如下处理:
根据catchError块,它将执行发布块。如果发布结果福尔斯失败类别,则将执行错误块以停止即将到来的阶段,如生产、预生产等。

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

fcipmucu6#

在所有答案的启发下,我将所有内容放在了一个脚本化管道中。请记住,这不是声明性管道。
要使此示例正常工作,您需要:

我的想法是,如果管道被“重放”,而不是通过“运行按钮”启动(在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
4szc88ey

4szc88ey7#

如果您能够批准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[]

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

23c0lvtd

23c0lvtd8#

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

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

q1qsirdb9#

这是在Jenkins UI中中止当前运行的构建管道的方法(在构建历史中有一个取消按钮),用于捕获:

相关问题