How to make jenkins job unstable from a bash script? - jenkins

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

Related

Jenkins treats any non-zero exit code as error

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).

Jenkins cucumber reports

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'

Jenkins scripted pipeline - sh return nonzero exit code but stage SUCCEEDS

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

setting status of a build in jenkins

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

Jenkinsfile pipeline, return warning but do not fail

Is there a way to not fail with a declarative pipeline step but display a warning instead? At the moment I am circumventing it by adding || exit 0 to the end of the sh command lines so it always exits ok.
Example currently:
sh 'vendor/bin/phpcs --report=checkstyle --report-file=build/checkstyle.xml --standard=phpcs.xml . || exit 0'
I feel there should be a better way of doing this? How can you control the result returned so the user knows with out digging through result logs but with out blocking/failing too?
Thank you
Edit:
So I have got this far to be able to mark it as unstable. In Blue Ocean it just marks every stage as unstable though and you have to go digging through to find it. Am I trying to do the impossible (but feels like I should be able to do it)?
Also it just displays it as 'Shell script' in the heading on Blue Sky now instead of showing the command being run so you don't even know what it's doing with out expanding each of them.
script {
def RESULT = sh returnStatus: true, script: 'vendor/bin/phpcs --report=checkstyle --report-file=build/checkstyle.xml --standard=phpcs.xml .'
if ( RESULT != 0 ) {
currentBuild.result = 'UNSTABLE'
}
}
Re marking it all yellow/unstable: Just found this which explains that I am not going mad. Several years of discussion and no progress :( https://issues.jenkins-ci.org/browse/JENKINS-39203
Re it just showing 'Shell script' now on Blue Ocean view: I'll go and play some more and see if I'm better with || exit 0 or a script block and using echo to display some useful info.
FYI: JENKINS-39203 has been resolved in the meantime.
Instead of setting currentBuild.result = 'UNSTABLE' we use the corresponding basic pipeline step unstable, which also takes a message:
unstable("There are Checkstyle issues")
You can find options for any steps in your jenkins itself under http://jenkins-url/pipeline-syntax/. sh with returnStatus: true can be used to achieve your goal.
sh returnStatus: true, script: 'ls -2' # returnStatus: true, just set $? but not fail the execution
Below pasted the screenshot from pipeline-syntax page:

Resources