Jenkins 管道:运行 阶段中的所有步骤,即使第一个失败
Jenkins pipeline: Run all steps in stage, even if the first one fails
我在某个阶段有一系列步骤想 运行 即使第一个步骤失败了。我希望阶段结果失败并中止构建,但只有 在 之后所有步骤都有 运行。例如,
pipeline {
agent any
stages {
stage('Run Test') {
steps {
sh "echo running unit-tests"
sh "echo running linting && false" // failure
sh "echo generating report" // This should still run (It currently doesn't)
publishCoverage adapters: [coberturaAdapter("coverage.xml")] // This should still run (It currently doesn't)
junit 'unit-test.xml' // This should still run (It currently doesn't)
}
}
stage('Deploy') {
steps {
echo "deploying" // This should NOT run
}
}
}
}
结果应该是构建失败,其中“运行 测试”阶段失败而“部署”阶段没有 运行。这可能吗?
P.S.
我不要求与Continue Jenkins pipeline past failed stage中相同的行为。我想 运行 失败后的步骤,但不是之后的任何阶段。我试图用 catchError (buildResult: 'FAILURE', stageResult: 'FAILURE')
包含每个测试步骤,但“部署”阶段仍然 运行s.
编辑:
我无法将所有步骤组合成一个大 sh
步骤并捕获其 return 代码,因为有些步骤不是 shell 命令,而是 jenkins 步骤,例如 junit
和 publishCoverage
.
理论上你应该可以使用 sh "<command>||true"
它会忽略命令上的错误并继续。但是,Jenkins 不会失败,因为它会忽略错误。
如果您不希望 Jenkins 忽略错误并希望它在阶段结束时停止,您可以执行以下操作:sh "<command>||$error=true"
然后根据 [=12= 使构建失败] 多变的。 (sh "$error"
可能就足够了,但我不确定,最后可能需要一个 if 语句。)它只会设置为 true
iff command
失败。
具有非零退出代码的脚本将始终导致 jenkins 步骤失败。您可以将 returnStatus
用作 true
,这样 jenkins 就不会失败。
另外考虑您的用例,您可以使用 post always
执行,以便始终执行这些步骤。
请参阅下面的参考示例:
stage('Run Test') {
steps {
def unit_test_result= sh returnStatus: true, script: 'echo "running unit-tests"'
def lint_result= sh returnStatus: true, script: 'echo "running linting"'
if (unit_test_result!=0 || lint_result!=0 ) {
// If the unit_test_result or lint_result status is not 0 then mark this stage as unstable to continue ahead
// and all later stages will be executed
unstable ('Testing failed')
// You can also mark as failed as below and it will not conintue other stages:
// error ('Testing failed')
}
}
post {
always {
// This block would always be executed inspite of failure
sh "echo generating report"
publishCoverage adapters: [coberturaAdapter("coverage.xml")]
junit 'unit-test.xml'
}
}
}
另一种选择是将构建步骤包装在 try-catch 块中!如果有异常,即 return 构建代码不是 0,您可以捕获它,将构建标记为不稳定,然后管道的其余部分继续。
这是一个例子`
管道 {
agent {
node {
label 'linux'
}
}
options {
timestamps()
disableConcurrentBuilds()
buildDiscarder(logRotator(numToKeepStr: '3'))
}
tools {
maven 'Maven 3.6.3'
jdk 'jdk11'
}
stages {
stage('CleanWS') {
steps {
cleanWs()
}
}
stage('Build') {
steps {
withMaven(options: [artifactsPublisher(disabled: true)]) {
sh "export NLS_LANG=GERMAN_GERMANY.WE8ISO8859P1 && mvn -f pom.xml clean install -DskipTests -Pregression-test -Dmaven.javadoc.skip=true"
}
}
}
stage('Test') {
steps {
script {
try {
withMaven(options: [artifactsPublisher(disabled: true)]) {
sh "export MAVEN_OPTS=\"-Xmx2048m\" && export NLS_LANG=GERMAN_GERMANY.WE8ISO8859P1 && mvn -B verify -Dmaven.source.skip=true -Dmaven.javadoc.skip=true"
}
} catch (exc) {
currentBuild.result = 'UNSTABLE'
}
}
}
post {
always {
script {
junit "**/surefire-reports/*.xml"
}
}
}
}
stage('Sonar Analyse') {
steps {
script {
withMaven(options: [artifactsPublisher(disabled: true)]) {
withSonarQubeEnv("SonarQube") {
sh "export MAVEN_OPTS=\"-Xmx2048m\" && export NLS_LANG=GERMAN_GERMANY.WE8ISO8859P1 && mvn sonar:sonar"
}
}
}
}
}
stage('Deploy to Nexus') {
steps {
sh "export NLS_LANG=GERMAN_GERMANY.WE8ISO8859P1 && mvn -f pom.xml -B clean deploy -DdeployAtEnd=true -DskipTests"
}
}
}
post {
failure {
script {
emailext(
body: "Please go to ${env.BUILD_URL}/console for more details.",
to: emailextrecipients([developers(), requestor()]),
subject: "Nightly-Build-Pipeline Status is ${currentBuild.result}. ${env.BUILD_URL}"
)
}
}
unstable {
script {
emailext(
body: "Please go to ${env.BUILD_URL}/console for more details.",
to: emailextrecipients([developers(), requestor()]),
subject: "Nightly-Build-Pipeline Build Status is ${currentBuild.result}. ${env.BUILD_URL}"
)
}
}
}
}`
我发现了一种获得我想要的行为的稍微有点老套的方法。其他答案对我不起作用,因为它们需要所有步骤都是 sh
个步骤,或者它们不会停止 运行 的 deploy
阶段。我使用 catchError
来设置构建和阶段结果。但是为了防止下一阶段 运行,我需要在阶段失败时显式调用 error
。
pipeline {
agent any
stages {
stage('Run Test') {
steps {
script {
// catchError sets the stageResult to FAILED, but does not stop next stages from running
catchError (buildResult: 'FAILURE', stageResult: 'FAILURE') {
sh "echo running unit-tests"
}
catchError (buildResult: 'FAILURE', stageResult: 'FAILURE') {
sh "echo running linting && false" // failure
}
catchError (buildResult: 'FAILURE', stageResult: 'FAILURE') {
sh "echo generating report" // This still runs
}
publishCoverage adapters: [coberturaAdapter("coverage.xml")] // This still runs
junit 'unit-test.xml' // This still runs
if (currentBuild.result == "FAILURE") { // This is needed to stop the next stage from running
error("Stage Failed")
}
}
}
}
stage('Deploy') {
steps {
echo "deploying" // This should NOT run
}
}
}
}
我在某个阶段有一系列步骤想 运行 即使第一个步骤失败了。我希望阶段结果失败并中止构建,但只有 在 之后所有步骤都有 运行。例如,
pipeline {
agent any
stages {
stage('Run Test') {
steps {
sh "echo running unit-tests"
sh "echo running linting && false" // failure
sh "echo generating report" // This should still run (It currently doesn't)
publishCoverage adapters: [coberturaAdapter("coverage.xml")] // This should still run (It currently doesn't)
junit 'unit-test.xml' // This should still run (It currently doesn't)
}
}
stage('Deploy') {
steps {
echo "deploying" // This should NOT run
}
}
}
}
结果应该是构建失败,其中“运行 测试”阶段失败而“部署”阶段没有 运行。这可能吗?
P.S.
我不要求与Continue Jenkins pipeline past failed stage中相同的行为。我想 运行 失败后的步骤,但不是之后的任何阶段。我试图用 catchError (buildResult: 'FAILURE', stageResult: 'FAILURE')
包含每个测试步骤,但“部署”阶段仍然 运行s.
编辑:
我无法将所有步骤组合成一个大 sh
步骤并捕获其 return 代码,因为有些步骤不是 shell 命令,而是 jenkins 步骤,例如 junit
和 publishCoverage
.
理论上你应该可以使用 sh "<command>||true"
它会忽略命令上的错误并继续。但是,Jenkins 不会失败,因为它会忽略错误。
如果您不希望 Jenkins 忽略错误并希望它在阶段结束时停止,您可以执行以下操作:sh "<command>||$error=true"
然后根据 [=12= 使构建失败] 多变的。 (sh "$error"
可能就足够了,但我不确定,最后可能需要一个 if 语句。)它只会设置为 true
iff command
失败。
具有非零退出代码的脚本将始终导致 jenkins 步骤失败。您可以将 returnStatus
用作 true
,这样 jenkins 就不会失败。
另外考虑您的用例,您可以使用 post always
执行,以便始终执行这些步骤。
请参阅下面的参考示例:
stage('Run Test') {
steps {
def unit_test_result= sh returnStatus: true, script: 'echo "running unit-tests"'
def lint_result= sh returnStatus: true, script: 'echo "running linting"'
if (unit_test_result!=0 || lint_result!=0 ) {
// If the unit_test_result or lint_result status is not 0 then mark this stage as unstable to continue ahead
// and all later stages will be executed
unstable ('Testing failed')
// You can also mark as failed as below and it will not conintue other stages:
// error ('Testing failed')
}
}
post {
always {
// This block would always be executed inspite of failure
sh "echo generating report"
publishCoverage adapters: [coberturaAdapter("coverage.xml")]
junit 'unit-test.xml'
}
}
}
另一种选择是将构建步骤包装在 try-catch 块中!如果有异常,即 return 构建代码不是 0,您可以捕获它,将构建标记为不稳定,然后管道的其余部分继续。
这是一个例子` 管道 {
agent {
node {
label 'linux'
}
}
options {
timestamps()
disableConcurrentBuilds()
buildDiscarder(logRotator(numToKeepStr: '3'))
}
tools {
maven 'Maven 3.6.3'
jdk 'jdk11'
}
stages {
stage('CleanWS') {
steps {
cleanWs()
}
}
stage('Build') {
steps {
withMaven(options: [artifactsPublisher(disabled: true)]) {
sh "export NLS_LANG=GERMAN_GERMANY.WE8ISO8859P1 && mvn -f pom.xml clean install -DskipTests -Pregression-test -Dmaven.javadoc.skip=true"
}
}
}
stage('Test') {
steps {
script {
try {
withMaven(options: [artifactsPublisher(disabled: true)]) {
sh "export MAVEN_OPTS=\"-Xmx2048m\" && export NLS_LANG=GERMAN_GERMANY.WE8ISO8859P1 && mvn -B verify -Dmaven.source.skip=true -Dmaven.javadoc.skip=true"
}
} catch (exc) {
currentBuild.result = 'UNSTABLE'
}
}
}
post {
always {
script {
junit "**/surefire-reports/*.xml"
}
}
}
}
stage('Sonar Analyse') {
steps {
script {
withMaven(options: [artifactsPublisher(disabled: true)]) {
withSonarQubeEnv("SonarQube") {
sh "export MAVEN_OPTS=\"-Xmx2048m\" && export NLS_LANG=GERMAN_GERMANY.WE8ISO8859P1 && mvn sonar:sonar"
}
}
}
}
}
stage('Deploy to Nexus') {
steps {
sh "export NLS_LANG=GERMAN_GERMANY.WE8ISO8859P1 && mvn -f pom.xml -B clean deploy -DdeployAtEnd=true -DskipTests"
}
}
}
post {
failure {
script {
emailext(
body: "Please go to ${env.BUILD_URL}/console for more details.",
to: emailextrecipients([developers(), requestor()]),
subject: "Nightly-Build-Pipeline Status is ${currentBuild.result}. ${env.BUILD_URL}"
)
}
}
unstable {
script {
emailext(
body: "Please go to ${env.BUILD_URL}/console for more details.",
to: emailextrecipients([developers(), requestor()]),
subject: "Nightly-Build-Pipeline Build Status is ${currentBuild.result}. ${env.BUILD_URL}"
)
}
}
}
}`
我发现了一种获得我想要的行为的稍微有点老套的方法。其他答案对我不起作用,因为它们需要所有步骤都是 sh
个步骤,或者它们不会停止 运行 的 deploy
阶段。我使用 catchError
来设置构建和阶段结果。但是为了防止下一阶段 运行,我需要在阶段失败时显式调用 error
。
pipeline {
agent any
stages {
stage('Run Test') {
steps {
script {
// catchError sets the stageResult to FAILED, but does not stop next stages from running
catchError (buildResult: 'FAILURE', stageResult: 'FAILURE') {
sh "echo running unit-tests"
}
catchError (buildResult: 'FAILURE', stageResult: 'FAILURE') {
sh "echo running linting && false" // failure
}
catchError (buildResult: 'FAILURE', stageResult: 'FAILURE') {
sh "echo generating report" // This still runs
}
publishCoverage adapters: [coberturaAdapter("coverage.xml")] // This still runs
junit 'unit-test.xml' // This still runs
if (currentBuild.result == "FAILURE") { // This is needed to stop the next stage from running
error("Stage Failed")
}
}
}
}
stage('Deploy') {
steps {
echo "deploying" // This should NOT run
}
}
}
}