Jenkins Pipeline terminated after sh returnStdout exit code nonzero - groovy

I have a groovy function to fetch the code coverage after apex run test execution.
def jsonResult = sh returnStdout: true, script: "sfdx force:apex:test:report --testrunid ${testRunId} --resultformat json --targetusername ${username} --codecoverage"
def coverageResult = readJSON text: jsonResult?.trim()
String coverageOutput = coverageResult.result.summary.testRunCoverage;
Double coverageAsDouble = Double.parseDouble(coverageOutput.replace("%",""));
if(coverageAsDouble >= 75) {
echo "Succesfully run test!"
}else {
error "Code coverage less than expected: ${ coverageOutput }"
}
If one or more test classes failed, it will return exit code 100 and the step failed.
ERROR:hudson.AbortException: script returned exit code 100
Is there any way to get the JSON response from sh by ignoring the exit code to process the next step?

Related

How to access groovy function inside sh in below jenkins pipeline script

def Greet(name) {
echo "Hello ${name}"
}
pipeline {
agent any
stages {
stage('Test') {
steps {
sh """
Greet('Build Team')
"""
}
}
}
}
I am trying to call 'Greet' function from the stage 'Test' inside the shell . But getting error as
/var/lib/jenkins/workspace/Check1#tmp/durable-ce807c1d/script.sh: line 2: syntax error near unexpected token `'Bob''
Any one let me know how we can call 'Greet' function from the stage 'Test' inside the shell .

How do i pass result from waited npm script to bash script?

In my npm script i have the following:
#!/usr/bin/env node
import { main } from './main';
import { CONFIG } from '../config';
(async () => {
const res = await main(CONFIG);
process.stdout.write(res.join('\n'));
return res;
})();
Now want to do some stuff depending on what's been returned in bash script. Attempts to do it so won't work properly:
npm run update-imports &
PID=$!
UpdateResult=$(wait $PID)
if [ -z "$UpdateResult" ];
then
echo "No imports updated, committing changes"
else
echo "Check the following files:\n ${UpdateResult}"
exit 1
fi
In short - if nothing or empty string returned - proceed with executing script, otherwise - exit script with warning.
How do i make it work?
In bash, wait returns the exit value of the process. Not the standard output as you expect. You can use process.exit(value) to return a value.
If you want to capture and process the standard output of node program, see the answer to question: How do I set a variable to the output of a command in Bash?
This should do the work:
UpdateResult=$(npm run update-imports)
if [ -z "$UpdateResult" ];
then
echo "No imports updated, committing changes"
else
echo "Check the following files:\n ${UpdateResult}"
exit 1
fi

Reading an environment variable set by a test in Jenkins pipeline

Not found any reference to this particular question.
I am looking to find a way to achieve something like this in a Jenkins pipeline which runs our acceptance tests using Protractor and Cucumber.js:
steps {
container('selenium') {
script {
try {
{
//run tests
}
}
catch (err) {
if (env.testFailed == 'true') {
println "A test failure exists - build status updated to failure"
currentBuild.result = 'FAILURE'
error "Test(s) have failed"
}
else {
println "No test failures exist - build status updated to success"
currentBuild.result = 'SUCCESS'
}
}
}
}
}
This would fail the build if the env var of testFailed is 'true'. The reason for this is we are encountering bugs with Protractor-Cucumber framework where if a failed test retries and passes the exit code of the stage is still 1.
So in the After hook of each test I am setting the env var using node.js to true if the Scenario status is failed:
if (scenario.result.status === Status.FAILED) {
process.env.testFailed = 'true';
}
if (scenario.result.status === Status.PASSED) {
process.env.testFailed = 'false';
}
The problem I have found is that the Jenkins pipeline fails to read the env var value in the code block of the catch section. It is always null.
Any ideas?
1) change the After hook to write the true/false flag to a file in sync.
2) read the file in catch block
catch(err) {
testFailed = sh(script:'cat result.flag.txt', returnStdout: true).trim()
if(testFailed == 'true') {
...
}
}
Another option if there is total/passed/failed case number in output of npm test
lines = []
try {
lines = sh(script:'npm test', returnStdout: true).readLines();
}
catch(err) {
size = lines.size()
// parse the last 20 lines to extract fail/pass/total number
for(int i=size-20;i<size;i++) {
line[i]
}
}
WHY IT DOESN'T WORK NOW?
I see that you're running your tests in a container. When you set an environment variable, it's reflected on the scope of your container not the Jenkins master server
WHAT YOU COULD TRY TO DO
This actually depends on how you run the tests, but this should be an option
// run tests here
// you should have a variable for your container
def exit_code = sh(script: "sudo docker inspect ${container.id} --format='{{.State.ExitCode}}'", returnStdout: true)
sh "exit ${exit_code}"
This actually also depends how you start the tests inside the container,
So if you update your answer with this information I could help you

Can a shell function behave as a command when it comes to failure status?

For a executable which can fail with not zero exit codes, one can do:
executable && echo "suceed" || echo "failure"
How to do this with a shell function?
myfunction() {
executable arg1 arg2
}
myfunction && echo "succeed" || echo "failure"
From the bash manual:
When executed, the exit status of a function is the exit status of the last command executed in the body.
In other words, shell functions behave exactly as you have demonstrated in your question. For example, given:
myfunction() {
false
}
Running:
myfunction && echo success || echo failed
Results in:
failed
On the other hand, if we have:
myfunction() {
true
}
Running the same command returns success.

SOAPUI Assertion script writing twice to file

I am writing a groovy script where I am extracting text from a response and writing it to an output file on my system. The problem I encounter is when I run the groovy script that calls the test. The script assertions runs and logs the text twice to the file.
It seems to write to the file just before it leaves the assertion.
I have tried the following:
...
...
if (context.alreadyWritten == null || !context.alreadyWritten) {
inputFile.append (testString+ "\n")
log.info testString
} else {
log.info ('Already written!')
}
I have set the flag (context.alreadyWritten) to false in groovy before I execute the test step.
SOAPUI version : 5.3.0
I see there was an issue previous with Smartbear when appending to file in an assertion script. However the workaround was advised to resolve this:
if (context.alreadyWritten == null || !context.alreadyWritten) {
}
Which does not resolve my issue
When I log the result using log.info I see only one instance of the message been logged.
Any ideas.
Thanks
If you are using Script Assertion, try below:
//Define the file name, change as needed
def fileName = '/path/to/file.xml'
//check if you got the response
if (context.response) {
log.info 'Response available and not empty'
def file = new File(fileName)
if (!context?.alreadySaved) {
file.write(context.response)
context.alreadySaved = true
log.info 'response written to file'
} else {
log.info 'Response already written'
}
} else {
log.info 'there is no response to save'
}

Resources