I have a jenkins job.
It is pretty simple: pull from git, and run the build.
The build is just one step:
Execute window command batch
In my use case, I will need to run some python scripts.
Some will fail, some others will not.
python a.py
python b.py
What does determine the final status of the build?
It seems I can edit that by:
echo #STABLE > build.proprieties
but how are the STABLE/UNSTABLE status assigned if not specified by the user?
What happens if b.py raise an error and fails?
Jenkins interprets a pipeline as failed if a command returns an exit code unequal zero.
Internally the build status is set with currentBuild.currentResult which can have three values: SUCCESS, UNSTABLE, or FAILURE.
If you want to control the failure / success of your pipeline yourself you can catch exceptions / exit codes and manually set the value for currentBuild.currentResult. Plugins also use this attribute to change the result of the pipeline.
For example:
stage {
steps {
script {
try {
sh "exit 1" // will fail the pipeline
sh "exit 0" // would be marked as passed
currentBuild.currentResult = 'SUCCESS'
} catch (Exception e) {
currentBuild.currentResult = 'FAILURE'
// or currentBuild.currentResult = 'UNSTABLE'
}
}
}}
Related
This is a concern as we have an executable which returns 2 as warning. We do not want to fail the Jenkins build pipeline just because of this. How can we modify the pipeline to accept an exit code 2, and prints out a reasonable warning message based on the exit code?
D:\Stage>c:\bin\mycommand
script returned exit code 2
When you run sh or bat in a Jenkins pipeline it will always fail the build (and throw an exception) for any non zero exit code - and that cannot be changed.
What you can do is use the returnStatus of the sh step (or cmd) which will return the exit code of the script instead of failing the build, and then you can use something like:
pipeline {
agent any
stages {
stage('Run Script') {
steps {
script {
def exitCode = sh script: 'mycommand', returnStatus: true
if (exitCode == 2) {
// do something
}
else if (exitCode){
// other non-zero exit codes
}
else {
// exit code 0
}
}
}
}
}
}
The only drawback of this approach is that returnStatus cannot be used together with returnStdout, so if you need to get the returned output you will need to get it in another way (write to file and then read it for example).
I'm using Cucumber reports plugin in my declarative pipeline like that:
cucumber '**/cucumber.json'
I'm able to check if some tests fail through link on the sidebar, but do I need to do something to mark the stage containing cucumber.json check as failed if some cucumber reports are failed? Because the problem is the build and stage are both green and successful despite there are some failed cucumber reports.
Jenkins version is 2.176.3
Cucumber reports version is 4.10.0
Cucumber command you are using just generates the report regardless the test result.
So yes, you have to make your pipeline fail somehow as the problem you are facing is that your test command is not returning making your pipeline fail.
The way to go is to make that the command that runs the tests returns non-zero exit code (exit 1) if something went wrong on your tests. That would make your pipeline stage to go red.
In case you run your tests using Maven this would be automatically managed on 'mvn test' (or whatever).
Otherwise, if you cannot do that, you will have to manage to make something like for example an sh script
that returns the exit code (0 pass / 1 fail) or a groovy function inside 'script' tag that sets the pipeline currentBuild.result value:
def checkTestResult() {
// Check some file to see if tests went fine or not
return 'SUCCESS' // or 'FAILURE'
}
...
stage {
script {
currentBuild.result = checkTestResult()
if (currentBuild.result == 'FAILURE') {
sh "exit 1" // Force pipeline exit with build result failed
}
}
}
...
I recommend you to use cucumber command on a 'always' post build action of your declarative pipeline
as it is a step that you will likely execute every time at the end of the pipeline either if it passes or fails. See the following example:
pipeline {
stages {
stage('Get code') {
// Whatever
}
stage('Run tests') {
steps {
sh "mvn test" // run_tests.sh or groovy code
}
}
}
post {
always {
cucumber '**/cucumber.json'
}
}
}
It is possible to set BuildStatus : 'FAILURE' to mark build as failed if a report marked as failed.
cucumber fileIncludePattern: '**/cucumber.json', buildStatus: 'FAILURE'
In my Jenkins scripted pipeline, I have a build stage that has the following sh command:
def buildcmd = "./scriptname.sh"+ <paramters>
def status = sh returnStatus: true, script:"""cd /to/some/dir
eval ${buildcmd}
"""
if(status != 0)
{
error("Failure")
}
After execution, scriptname exits with status 2 and status variable also contains 2 and the job fails. But however the stage result is shown as SUCCESS. I expected both the stage result and build result to be FAILURE.
Can anybody please clarify this.
returnStatus (optional)
Normally, a script which exits with a nonzero
status code will cause the step to fail with an exception. If this
option is checked, the return value of the step will instead be the
status code. You may then compare it to zero, for example.
Source
If your goal is to simply let the stage fail use returnStatus: false. Unfortunately I can't tell you the difference between a status code and exit code (like mentioned above). The documentation only tells that if you set returnStatus: true the pipeline won't fail on an exit code unequal 0.
You can set the result of the pipeline by yourself (Source):
if(status != 0)
{
currentBuild.result = 'FAILURE'
}
In most of my jenkins jobs, I have bash script.
In some conditions, I want to make my build instable.
When I exit the script with the code 0, the build finish in SUCCESS (GREEN COLOR) and when I exit with another code the job is failed (RED COLOR).
Is there a way to make the jenkins job unstable (YELLOW COLOR) from a bash script ?
If you use the pipeline plugin and write your jobs in groovy pipline dsl, yes:
try {
sh "yourscript.sh"
} catch(Exception e) {
currentBuild.result = 'UNSTABLE'
}
Jenkins is designed to set an automatic fail when the exit code of your script is 1. There are plenty of ways of overriding this, but most involve Jenkins CLI or a plugin. Using the returnStatus flag for shell commands https://jenkins.io/doc/pipeline/steps/workflow-durable-task-step/, Jenkins will not automatically fail but instead, return the status code.
Here's the documentation:
returnStatus (optional)
Normally, a script which exits with a nonzero status code will cause the step to fail with an exception. If this option is checked, the return value of the step will instead be the status code. You may then compare it to zero, for example.
script{
def returnVal = sh(
returnStatus: true,
script: '''
**your script here**
'''
)
if(returnVal != 0) {
currentBuild.result = 'UNSTABLE'
}
}
I'm trying to replicate the equivalent of a conditional stage in Jenkins pipeline using a try / catch around a preceding stage, which then sets a success variable, which is used to trigger the conditional stage.
It appears that a try catch block is the way to go, setting a success var to SUCCESS or FAILED, which is used as part of a when statement later (as part of the conditional stage).
The code I am using is as follows:
pipeline {
agent any
stages {
try{
stage("Run unit tests"){
steps{
sh '''
# Run unit tests without capturing stdout or logs, generates cobetura reports
cd ./python
nosetests3 --with-xcoverage --nocapture --with-xunit --nologcapture --cover-package=application
cd ..
'''
currentBuild.result = 'SUCCESS'
}
}
} catch(Exception e) {
// Do something with the exception
currentBuild.result = 'SUCCESS'
}
stage ('Speak') {
when {
expression { currentBuild.result == 'SUCCESS' }
}
steps{
echo "Hello, CONDITIONAL"
}
}
}
}
The latest syntax error I am receiving is as follows:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup
failed:
WorkflowScript: 4: Expected a stage # line 4, column 9.
try{
I've also tried lots of variations.
Am I taking the wrong approach here? This seems like a fairly common requirement.
Thanks.
This might solve your problem depending on what you are going for. Stages are only run when the preceding stages succeed, so if you actually have two stages like in your example, and if you want the second to only run when the first succeeds, you want to ensure that the first stage fails appropriately when tests fail. Catching will prevent the (desirable) failure. Finally will preserve the failure, and can also still be used to grab your test results.
So here, the second stage will only run when the tests pass, and the test results will be recorded regardless:
pipeline {
agent any
stages {
stage("Run unit tests"){
steps {
script {
try {
sh '''
# Run unit tests without capturing stdout or logs, generates cobetura reports
cd ./python
nosetests3 --with-xcoverage --nocapture --with-xunit --nologcapture --cover-package=application
cd ..
'''
} finally {
junit 'nosetests.xml'
}
}
}
}
stage ('Speak') {
steps{
echo "Hello, CONDITIONAL"
}
}
}
}
Note that I'm actually using try in a declarative pipeline, but like StephenKing says, you can't just use try directly (you have to wrap arbitrary groovy code in the script step).