Passing Java exception to JenkinsFile - jenkins

I am invoking a Java class as part of my Jenkins pipleine. I want to pass or fail the pipeline based on the exception retureeened from the main class. I am trying something like this.
script{
try{
sh ' mvn exec:java -Dexec.mainClass="com..test.Deployer" -Dexec.args="qal"'
}catch (Exception e) {
echo 'exception::' + e.toString()
echo 'message::' + e.getMessage()
echo 'cause::' + e.getCause()
if (e.toString().contains("NoChangeDetectedException")) {
currentBuild.result = 'SUCCESS'
return
}
}
}
But from the Jenkins log, I see the original exception is not getting passed.
An exception occured while executing the Java class. null: InvocationTargetException:
exception:: hudson.AbortException: script returned exit code 1
message:: script returned exit code 1
cause:: null
Is it possible to get the actual message in the Jenkins file?
Note: getStackTrace is not permitted for our pipeline.

The exception(InvocationTargetException) you caught is not threw by java class(com..test.Deployer), it is threw by sh step, so there is no message or stackTrace about your class com..test.Deployer.
Meanwhile, sh step doesn't provide a good way to capture stderr, and the returnStdout parameter of sh doesn't work when script exit with error.
There is a workground to get the mvn output, by write mvn output to a temp file, using -DoutputFile
script {
stderrfile = 'stderr.out' //temp file
shout = '' //doesn't work for this question
try{
shout = sh(returnStdout: true, script: "mvn exec:java -Dexec.mainClass='com..test.Deployer' -Dexec.args='qal' -DoutputFile=${stderrfile}")
echo 'shout::' + shout
}catch (Exception e) {
errmsg = readFile(stderrfile)
echo 'errmsg::' + errmsg
echo 'shout::' + shout
echo 'exception::' + e.toString()
echo 'message::' + e.getMessage()
echo 'cause::' + e.getCause()
if (e.toString().contains("NoChangeDetectedException")) {
currentBuild.result = 'SUCCESS'
return
}
}
}
The error message will be in the errmsg = readFile(stderrfile).

Related

How can I mark a stage as FAILED but continue its execution in Jenkins?

Here's my code, it uses jenkins-plugin:
pipeline
{
agent any
stages
{
stage ('Run Demos')
{
def demoPath = '"' + env.WORKSPACE + 'MyDemo.exe"'
def demoNames = ["demo1", "demo2"]
for (demoName in demoNames)
{
bat('start /b /wait "" ' + demoPath + ' ' + demoName)
}
}
}
}
When bat('start /b /wait "" ' + demoPath + ' ' + demoName) fails inside the loop, the whole stage is stopped. I can workaround this by adding a try-catch or catchError block around the bat call, but then the step is marked as SUCCESS (green) even if the return code marks FAILURE (red).
Is there a way I can mark the stage as FAILURE on error and NOT stop the execution of the remaining demos? I don't want to break each demo run into different stages.
In declarative pipelines, you can achieve this using the catchError block, like so:
stage ('Run Demos')
{
steps
{
def demoPath = '"' + env.WORKSPACE + 'MyDemo.exe"'
def demoNames = ["demo1", "demo2"]
for (demoName in demoNames)
{
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE')
{
bat('start /b /wait "" ' + demoPath + ' ' + demoName)
}
}
}
}
The overall build as well as the stage will be marked as FAILURE in case of exception, but the remaining demos and following stage will execute regardless.
Use SUCCESS or null to keep the buildResult from being set when an error is caught.
See also:
Pipeline: Basic Steps
Another option is to use currentBuild.result to set the status in the catch block.
script {
for (demoName in demoNames) {
try {
bat('start /b /wait "" ' + demoPath + ' ' + demoName)
} catch (e) {
currentBuild.result = 'FAILURE'
unstable("One of the demos failed")
}
}
}

ENV variable is not getting populated in shell script of groovy/jenkins pipeline

I am trying to populate an environment variable with the exit code status and use that in the catch block to avoid certain exceptions.
not able to store the exit code value to the env variable in groovy pipeline. Should I take a different approach here?
environment {
cmdStatus = 0
}
try{
image.inside("--env-file ${PWD}/creds.env -v /config/.ssh:/config/.ssh") {
sh """
python -u /config/env-python/abc.py -u ${update}
cmdStatus = \$? --> error exit code value is not getting stored in the env variable
"""
}
}
catch(Exception e) {
if (env.cmdStatus == 0) {
echo 'Inside Success'
} else {
echo 'Inside Failure'
}
}

Jenkinsfile - stop pipeline when catch error

I am having a problem with my pipelin in Jenkins.
I perform a path search for files with the specified extension. I then execute php -l with the previously found files.
Everything works ok but I would like if php -l finds an error then build and step go to UNSTABLE state and further execution of the pipeline is stopped.
I managed to do it this way but then build and step are in FAILED state
} catch (Exception e) {
error("${e}")
Part of code my pipeline.
def check(){
stage('Validate files') {
try {
sh "find . -type f -iregex '.*\\.\\(php\\)' | xargs -I % sh -c 'php -l \'%\''"
} catch (Exception e) {
error("${e}")
}
}
}
I hope someone smarter can direct me to a solution :)
Got an example to work but maybe not exactly what you wanted. I used unstable() to mark the stage / build and then checked for the exit code of the sh step to return or continue the pipeline.
There are 2 if's as you need to return outside of a stage to not just return from the stage.
#!/usr/bin/env groovy
try {
node {
def exitCode = 0
exitCode = check()
if (exitCode != 0){
return
}
somethingelse()
}
} catch (Throwable err) { // catch all exceptions
throw err
} finally {}
def check(){
stage('Validate files') {
exitCode = sh script:"exit 1", returnStatus:true
if (exitCode !=0){
unstable('message')
}
}
return exitCode
}
def somethingelse(){
stage('Something'){
echo "somethingelse"
}
}

Jenkins Pipelien groovy string comparison not working

I am having a shared library in which there is a groovy script, that returns the status as 'FAIL' or 'SUCCESS' at the end.I am using the status to FAIL the jenkins build if needed. Following is small snippet :
def res=generateStats()
print(' build result '+res)
if(res == "FAIL")
{
print(' enter1 ')
currentBuild.result = 'FAILURE'
}
else
print('no2')
if(res == 'FAIL')
{
print(' enter3 ')
currentBuild.result = 'FAILURE'
}
else
print('no23')
Output is :
17:41:51 build result FAIL
[Pipeline] echo
17:41:51 no2
[Pipeline] echo
17:41:51 no23
Why the code is not going in if branch and failing the pipeline? I used two if blocks to just test double or single quotes.The print statements are added to debug only
Try using string comparators .equal() instead of using ==

Jenkins error handling between scripted and declarative pipelines

I'd like to build a number of declarative pipeline jobs from a scripted pipeline, and handle any failures with individual try/catch blocks nested within a parent try/catch
node {
def err = false
try{
stage('build image') {
try {
//this job is a declarative pipeline
build job: 'build-docker-image'
} catch(e) {
echo "failure at build-docker-image"
throw e
}
}
stage('deploy image') {
try {
//this job is a declarative pipeline
build job: 'deploy-docker-image'
} catch(e) {
echo "failure at deploy-docker-image"
throw e
}
}
} catch(e) {
err = true
echo "caught error ${e}"
}
if(!err) {
echo "build and deploy ran successfully"
}
}
This code behaves inconsistently.
If the build job fails for syntactical reasons, the error is caught by the child try/catch and echos the error message, then throws it to the parent, which also catches it and echos the error itself.
But if the build job fails for less explicit reasons, i.e. the image isn't compiled correctly, the parent try/catch will still catch the error and behave the same as the previous example, but the child try/catch will not catch the error, and will not echo its failure message.
Why the discrepancy? Are there some errors caused by a failed declarative pipeline job that a try/catch block would not catch? Is it bad practice to mix scripted and declarative pipelines? I would be grateful for any advice or insight regarding this. Thank you
You are using same variable to catch error in try..catch loops.
Try this one:
def err = false
try{
stage('build image') {
try {
//this job is a declarative pipeline
build job: 'build-docker-image'
} catch(e) {
echo "failure at build-docker-image"
throw e
}
}
stage('deploy image') {
try {
//this job is a declarative pipeline
build job: 'deploy-docker-image'
} catch(e) {
echo "failure at deploy-docker-image"
throw e
}
}
} catch(error) {
err = true
echo "caught error ${error}"
}
if(!err) {
echo "build and deploy ran successfully"
}
}```

Resources