Jenkins管道-在pylint的条件故障下跳过下一阶段

时间:2020-04-22 15:41:00

标签: jenkins jenkins-pipeline jenkins-plugins pylint

我有一个Jenkinsfile,它有两个不同的阶段:Pre-BuildBuildPre-Build正在执行pylint,并使用warnings-ng插件将其报告给Jenkins。

类似的东西:

stages {
        stage('Pre-build') {
            steps {
                script {
                    sh """#!/usr/bin/env bash
                            pip install .
                            pylint --exit-zero --output-format=parseable --reports=n myProject > reports/pylint.log
                            """
                }
            }

            post {
                always {
                    recordIssues(
                            enabledForFailure: true,
                            tool: pyLint(pattern: '**/pylint.log'),
                            unstableTotalAll: 20,
                            failedTotalAll: 30,
                    )
                }
                failure {
                    cleanWs()
                }
            }
        }

        stage('Build') {
            steps {
                script {
                    sh """#!/usr/bin/env bash
                            set -e
                            echo 'I AM STAGE TWO AND I SHOULD NOT BE EXECUTED'
                            """
                }
            }
            post {
                always {
                    cleanWs()
                }
            }
        }
    }

我在这里遇到了两个问题。目前,我正在将pylint设置为--exit-zero,因为我想根据报告将warnings-ng插件确定是否可行。

目前,这总共失败了30次。现在,myProject有45个问题,我想防止进入下一阶段,Build。但是目前我似乎无法阻止这种行为,因为它一直持续到Build阶段。

由于recordIssues中确定的结果,该构建被标记为失败,但它不会中止该作业。

我在https://issues.jenkins-ci.orgTicket)上找到了一张票,但是我似乎无法理解所有这些。

3 个答案:

答案 0 :(得分:1)

我找到了解决您问题的方法,我认为这是管道工作流程中的错误。 warnings-ng正确地将构建状态设置为失败,但是尽管${currentBuild.currentResult}变量中的状态仍然可以开始下一阶段。

您可以使用when { expression { return currentBuild.currentResult == "SUCCESS" } }跳过后面的阶段,或者抛出错误。但是我认为这应该是默认行为。然后,您的文件应为:

stages {
        stage('Pre-build') {
            steps {
                script {
                    sh """#!/usr/bin/env bash
                            pip install .
                            pylint --exit-zero --output-format=parseable --reports=n myProject > reports/pylint.log
                            """
                }
            }

            post {
                always {
                    recordIssues(
                            enabledForFailure: true,
                            tool: pyLint(pattern: '**/pylint.log'),
                            unstableTotalAll: 20,
                            failedTotalAll: 30,
                    )
                }
            }
        }

        stage('Build') {
            when { expression { return currentBuild.currentResult == "SUCCESS" } }

            steps {
                script {
                    echo "currentResult: ${currentBuild.currentResult}"
                    sh """#!/usr/bin/env bash
                            set -e
                            echo 'I AM STAGE TWO AND I SHOULD NOT BE EXECUTED'
                            """
                }
            }

        }
        post {
            always {
                cleanWs()
            }
        }
    }

我在他们的吉拉(Jira)中创建了一个issue

我的环境:

Jenkins版本:2.222.1

warnings-ng版本:8.1

worfklow-api版本:2.40

答案 1 :(得分:0)

  1. 您使用过post 2次,这是错误的实现,因为post设计为在所有阶段完成后仅执行一次。它应该在流水线结束之前的所有阶段之后编写。
  2. 要停止或跳过第二个Build stage的执行,您可以在顶部创建全局变量,捕获pylint的输出,并在阶段开始时使用if或when条件。类似于-
pipeline {
def result

stages {
        stage('Pre-build') {
            steps {
                script {
                    sh """#!/usr/bin/env bash
                            pip install .
                            pylint --exit-zero --output-format=parseable --reports=n myProject > reports/pylint.log
                            """
                   }
                }
            }
        }
        stage('Pylint result') {   // Not sure how recordIssue works. This just an example.
         result =  recordIssues(
                            enabledForFailure: true,
                            tool: pyLint(pattern: '**/pylint.log'),
                            unstableTotalAll: 20,
                            failedTotalAll: 30,
                    )
        }
        stage('Build') {
          if ( result == "pass") {
            steps {
                script {
                    sh """#!/usr/bin/env bash
                            set -e
                            echo 'I AM STAGE TWO AND I SHOULD NOT BE EXECUTED'
                            """
                }
            }
         } 
       }
    }
   post {   // this should be used after stages
                always {
                    cleanWs()
                }   
            failure {
                    cleanWs()
                }
}

此外,阶段的设计方式是,如果它们失败,则将不执行下一个阶段,因此,最好在阶段内而不是在后置条件下执行pylint。

注意:上面的代码仅是示例。请根据需要进行修改。

答案 2 :(得分:0)

您可能会考虑的一种选择是使用以下代码明确使构建失败:

post {
    always {
        recordIssues(
            enabledForFailure: true,
            tool: pyLint(pattern: '**/pylint.log'),
            unstableTotalAll: 20,
            failedTotalAll: 30
        )

        script {
            if (currentBuild.currentResult == 'FAILURE') {
                error('Ensure that the build fails if the quality gates fail')
            }
        }
    }
}

在这里,在记录问题之后,还要检查currentBuild.currentResult的值是否为FAILURE,在这种情况下,您将显式调用error()函数,该函数会导致构建失败。 / p>