从Jenkins的管道中止当前构建

时间:2017-03-08 09:33:34

标签: jenkins jenkins-pipeline

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

7 个答案:

答案 0 :(得分:70)

您可以将构建标记为已中止,然后使用error步骤停止构建:

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

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

Pipeline Stage View

答案 1 :(得分:6)

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

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
}

答案 2 :(得分:1)

在Jenkins的这个documentation之后,您应该能够生成错误来停止构建并设置构建结果,如下所示:

currentBuild.result = 'ABORTED'

希望有所帮助。

答案 3 :(得分:1)

我以声明方式处理,如下所示:

基于catchError块,它将执行post块。  如果发布结果属于故障类别,则将执行错误块以停止后续阶段,例如生产,预生产等。

pipeline {

agent any

stages{
    stage('Build') {
        steps{
             catchError {
                sh 'sudo 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 'sudo bash path/To/Filename.sh'              
              }
        }
   }

}

答案 4 :(得分:1)

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

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

我的想法是中止管道,如果它被“重播”而不是由“运行按钮”启动(在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

答案 5 :(得分:0)

我们使用的是:

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

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

答案 6 :(得分:0)

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

<?php
/**
 * Template used for single posts and other post-types
 * that don't have a specific template.
 *
 * @package Avada
 * @subpackage Templates
 */

// Do not allow directly accessing this file.
if ( ! defined( 'ABSPATH' ) ) {
    exit( 'Direct script access denied.' );
}

?>
<?php get_header(); ?>

<section id="content" class="full-width" style="width: 100%;">

            <div id="post-15912" class="fusion-archive-description post-15912 avada_portfolio type-avada_portfolio status-publish format-standard has-post-thumbnail hentry portfolio_category-dumfries-and-galloway inn-features-coastal-breaks inn-features-countryside-walks inn-features-cycling-holidays inn-features-dog-friendly-pubs inn-features-fine-dining inn-features-fishing-holidays inn-features-romantic-getaways">
                <div class="post-content">
                    <?php
                    $portfolio_cat_slug = get_queried_object()->slug;
                    $portfolio_cat_name = get_queried_object()->name;
                    ?>
                    <h1><?php echo $portfolio_cat_name; ?></h1>
                    <?php echo category_description(); ?>

                    <div class="fusion-aligncenter" style="margin-top: 20px;"><a href="<?php get_site_url(); ?>/gift-vouchers/" class="fusion-button button-flat fusion-button-default-size button-default button-1 fusion-button-default-span fusion-button-default-type" style="margin-bottom: 20px;">Buy <?php echo $portfolio_cat_name; ?> Gift Vouchers</a></div> 

                </div>   
               <div class="fusion-posts-container fusion-blog-layout-grid fusion-blog-layout-grid-3 isotope fusion-blog-pagination " data-pages="2" style="position: relative; height: 1384.4px;">
            <?php
                $collection_post_args = array(
                    'post_type' => 'avada_portfolio', // Your Post type Name that You Registered
                    'posts_per_page' => 999,
                    'order' => 'DESC',
                    'tax_query' => array(
                        array(
                            'taxonomy' => 'inn-features',
                            'field' => 'slug',
                            'terms' => $portfolio_cat_slug
                        )
                    )
                );
                $collection_post_qry = new WP_Query($collection_post_args);

                if($collection_post_qry->have_posts()) :
                   while($collection_post_qry->have_posts()) :
                        $collection_post_qry->the_post(); 
            ?>
                   <article id="post-15912" class="fusion-post-grid  post fusion-clearfix post-15912 avada_portfolio type-avada_portfolio status-publish format-standard has-post-thumbnail hentry portfolio_category-dumfries-and-galloway inn-features-coastal-breaks inn-features-countryside-walks inn-features-cycling-holidays inn-features-dog-friendly-pubs inn-features-fine-dining inn-features-fishing-holidays inn-features-romantic-getaways" style="position: absolute; left: 0px; top: 0px; padding: 10px;">

                    <div class="fusion-post-wrapper">
                   <div class="fusion-flexslider flexslider fusion-post-slideshow">
                            <ul class="slides">
                                <li class="flex-active-slide" style="width: 100%; float: left; margin-right: -100%; position: relative; opacity: 1; display: block; z-index: 2;">

                                    <div class="fusion-image-wrapper" aria-haspopup="true"> 
                                        <a href="<?php the_permalink(); ?>"> 

                                            <?php $url = wp_get_attachment_url( get_post_thumbnail_id($post->ID), 'thumbnail' ); ?>

                                            <img width="384" height="173" alt="" data-src="<?php echo $url ?>" class="attachment-full size-full wp-post-image lazyloaded" src="<?php echo $url ?>" draggable="false">

                                        </a>
                                    </div>
                                </li>
                            </ul>

                        </div>

                        <div class="fusion-post-content-wrapper">
                            <div class="fusion-post-content post-content">
                        <h2 class="entry-title" itemprop="headline"><a href="<?php the_permalink(); ?>" class="entry-title-link"><?php  the_title(); ?></a></h2>
                            </div>


                        <div class="fusion-meta-info">
                                <div class="fusion-alignleft"> 
                                    <a href="<?php the_permalink(); ?>" class="fusion-read-more"> Read More </a>
                                </div>
                            </div>
                        </div>
                        </div>
                   </article>


            <?php
                    endwhile;
                    endif;



            ?>



    </div>
    </div>  

    <div class="fusion-aligncenter" style="margin-top: 20px;"><a href="<?php get_site_url(); ?>/gift-vouchers/" class="fusion-button button-flat fusion-button-default-size button-default button-1 fusion-button-default-span fusion-button-default-type">Buy <?php echo $portfolio_cat_name; ?> Gift Vouchers</a></div> 






        <?php if( have_rows('feature_repeater') ): ?>
 <div class="related-posts">
        <h2>You May Also Like...</h2>
    <div>

    <?php while( have_rows('feature_repeater') ): the_row(); 

        // vars
        $image = get_sub_field('collection_image');
        $content = get_sub_field('collection_title');
        $link = get_sub_field('collection_link');

        ?>

        <div>

            <?php if( $link ): ?>
                <a href="<?php echo $link; ?>">
            <?php endif; ?>

                <img src="<?php echo $image['url']; ?>" alt="<?php echo $image['alt'] ?>" />

            <?php if( $link ): ?>
                </a>
            <?php endif; ?>

            <?php echo $content; ?>

        </div>

    <?php endwhile; ?>


        </div>
</div>
<?php else : ?>

       No Posts to Display

<?php endif; ?>



</section>          
<?php do_action( 'avada_after_content' ); ?>
<?php get_footer(); ?>