Jenkins - script block multiple bash commands doesn't work [duplicate] - bash

I've defined If-Else in the jenkins script section. But it doesn't get executed at all. Any idea what's wrong.
script {
unit_test_result = sh (
script: ''' #!/bin/bash
mvn clean test | grep \'Tests run:\' | grep -v \'Time elapsed\'
if [[ $? == 1 ]];
then echo "No Unit tests to run!";
fi
''',
returnStdout: true
).trim()
}
But the if section doesn't run at all..
[Pipeline] script
[Pipeline]
[Pipeline]
+ grep Tests run:
+ mvn clean test
+ grep -v Time elapsed
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // node
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
Failed in branch Unit Tests

grep -v 'Time elapsed' exits with status code 1 only if every input line did not contain Time elapsed, but this will never happen as mvn seems to always print a summary.
According to this website, the output of mvn clean test looks as follows if there are tests
-------------------------------------------------------
T E S T S
-------------------------------------------------------
[...]
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.547 sec
[...]
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.018 sec
Results :
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
and according to this question, as follows if there are no tests
-------------------------------------------------------
T E S T S
-------------------------------------------------------
There are no tests to run.
Results :
Tests run: 0, Failures: 0, Errors: 0, Skipped: 0
In both cases, grep 'Tests run:' will print at least the summary in the last line. The summary never contains Time elapsed. Therefore grep -v 'Time elapsed' always exits with status code 0.
Try the following script instead:
#!/bin/bash
if ! mvn clean test | grep -q '^Tests run: [^0]'; then
echo "No Unit tests to run!";
fi
For the outputs shown in this question, we could use if mvn clean test | grep -Fxq 'There are no tests to run.' instead. But I found other sample outputs where mvn did not print that string; sometimes even no summary. The first script handles all of these cases too.

Related

Using variable as Jenkins input message text

i would like to use a variable as a message inside an input step inside a scripted pipeline.
stage("Manual Approval"){
sh """
ls -la
versionNumber=`grep -wE -A 2 '"package": "example0"'`
ancestorVersion=`grep -wE -A 2 '"package": "example"'`
"""
timeout(time: 120, unit: 'MINUTES') {
input message: "Do you want to build ver. ${versionNumber} having ver. ${ancestorVersion} as an ancestor?", submitter: 'user1'
}
}
In the latest version of the pipeline sh step allows save the output in a variable, following:
script {
INFO_SYSTEM = sh (
script: 'uname -a',
returnStdout: true
).trim()
echo "Value: ${INFO_SYSTEM}"
}
Output:
Running on Jenkins in /var/jenkins_home/workspace/testing
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Testing)
[Pipeline] script
[Pipeline] {
[Pipeline] sh
+ uname -a
[Pipeline] echo
Value: Linux d7d184735414 4.14.225-121.357.amzn1.x86_64 #1 SMP Mon Mar 15 23:52:05 UTC 2021 x86_64 GNU/Linux
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
So, maybe you can change the approach for do this task getting each variable in executing in a single command and retrieve the output, like this:
stage("Manual Approval"){
VERSION_NUMBER = sh (
script: 'grep -wE -A 2 '"package": "example0"'',
returnStdout: true
).trim()
ANCESTOR_VERSION = sh (
script: 'grep -wE -A 2 '"package": "example"'',
returnStdout: true
).trim()
timeout(time: 120, unit: 'MINUTES') {
input message: "Do you want to build ver. ${VERSION_NUMBER} having ver. ${ANCESTOR_VERSION} as an ancestor?", submitter: 'user1'
}
}

Jenkins pipeline not executing next stage after failure in one stage of running bash script

I am running a shell script inside a docker container via jenkins groovy pipeline script. The bash script sets some environment variables and then executes unit tests. The stdout of these unit test execution is dumped to a text file.
I later copy this text file outside of the container for usage.
Here is the shell script:
#/bin/bash
source /root/venv/bin/activate
export PYTHONPATH=/foo/bar
cd unit_tests
rm -f results.txt
python tests.py >> results.txt
My pipeline script is as follows:
stage('Run Unit Tests') {
steps {
sh '''
docker-compose -f ./dir1/docker-compose-test.yml up -d
docker cp /supporting_files/run_unit_tests.sh container_1:/foo/bar/
docker exec container_1 /bin/bash run_unit_tests.sh
docker cp container_1:/foo/bar/unit_tests/results.txt .
'''
}
}
stage('Reporting') {
steps {
//steps for reporting
}
}
The problem is whenever any test fails, the results.txt has the appropriate text about failures and their stack. But the pipeline stop executing saying
[Pipeline] }
ERROR: script returned exit code 1
Because of this I am not able to execute next steps of parsing the results.txt file and reporting the results.
How do I make the pipeline execute next stage ?
I tried some things like:
1. Using catchError:
stage('Run Unit Tests') {
steps {
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
sh '''
//Running the commands above
'''
}
}
}
Using try:
try{
stage('Run Unit Tests') {
sh '''
//Executing tests
'''
}
} catch(e) {
echo e.toString()
}
But both of them does not help.
Also the shell script simply dumps the stdout of running tests into a text file so I don't understand why an exit code 1 should be returned as the operation itself does not fail. I saw the text file later, it had the correct failures and error counts with stack.

Jenkins pipeline - How to read the success status of build?

Below is the output after running the build(with success):
$ sam build
2019-06-02 15:36:37 Building resource 'SomeFunction'
2019-06-02 15:36:37 Running PythonPipBuilder:ResolveDependencies
2019-06-02 15:36:39 Running PythonPipBuilder:CopySource
Build Succeeded
Built Artifacts : .aws-sam/build
Built Template : .aws-sam/build/template.yaml
Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Package: sam package --s3-bucket <yourbucket>
[command] && echo "Yes" approach did not help me.
I tried to use this in Jenkins pipeline
def samAppBuildStatus = sh(script: '[cd sam-app-folder; sam build | grep 'Succeeded' ] && echo true', returnStatus: true) as Boolean
as one-liner script command, but does not work
How to grab the success build status using bash script? for Jenkins pipeline
Use this to grab the exit status of the command:
def samAppBuildStatus = sh returnStatus: true, script: 'cd sam-app-folder; sam build | grep "Succeeded"'
or this if you don't want to see any stderr in the output:
def samAppBuildStatus = sh returnStatus: true, script: 'cd sam-app-folder; sam build 2>&1 | grep "Succeeded"'
then later in your Jenkinsfile you can do something like this:
if (!samAppBuildStatus){
echo "build success [$samAppBuildStatus]"
} else {
echo "build failed [$samAppBuildStatus]"
}
The reason for the ! is because the definitions of true and false between shell and groovy differ (0 is true for shell).

Get the cause of a Maven build failure inside a Jenkins pipeline

I have a Jenkins scripted pipeline set up where I execute a number of Maven builds. I want to treat one of them as non-fatal if the root cause is a known one.
I have tried to achieve that by inspecting the Exception's message, e.g.
try {
sh "mvn -U clean verify sonar:sonar ${sonarcloudParams}"
} catch ( Exception e ) {
if ( e.getMessage().contains("not authorized to run analysis")) {
echo "Marking build unstable due to missing SonarCloud onboarding. See https://cwiki.apache.org/confluence/display/SLING/SonarCloud+analysis for steps to fix."
currentBuild.result = 'UNSTABLE'
}
}
The problem is that the exception's message is not the one from Maven, but instead "script returned exit code 1".
There is no further information in e.getCause().
How can I access the cause of the Maven build failure inside my scripted pipeline?
You can get the command output, then parse it containers specific message.
def output = sh(
script: "mvn -U clean verify sonar:sonar ${sonarcloudParams}",
returnStdout: true
).trim()
echo "mvn cmd output: ${output}"
if(output.contains('not authorized to run analysis')) {
currentBuild.result = 'UNSTABLE'
}
// parse jenkins job build log
def logUrl = env.BUILD_URL + 'consoleText'
def cmd = "curl -u \${JENKINS_AUTH} -k ${logUrl} | tail -n 50"
def output = sh(returnStdout: true, script: cmd).trim()
echo "job build log: ${output}"
if(output.contains('not authorized to run analysis')) {
currentBuild.result = 'UNSTABLE'
}
One option is to inspect the last log lines using
def sonarCloudNotEnabled = currentBuild.rawBuild.getLog(50).find {
line -> line.contains("not authorized to run analysis")
}
However, this does not work by default. On the Jenkins instance I'm using it errors out with
Scripts not permitted to use method org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper getRawBuild. Administrators can decide whether to approve or reject this signature.

how parse console on travis-ci and find the number of occured word

I use github + travis-ci for continuous integration. I have a maven project with lot of tests. I want parse all console and find a special word by xpath. If this word is present x times my job is OK else my job is KO.
how parse console on travis-ci and find the number of occured word by xpath or other method?
Given log.txt as input, and desired input lines like these:
Tests run: 10, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 7.957 sec - in TestSuite
Tests run: 10, Failures: 0, Errors: 0, Skipped: 0
Assuming we just want to test the "10", this might do:
n=5
awk -F '[ ,]*' '/^Tests run:/ \
{ if ($3>'$n') { print "OK found " $3 ; x=$3 ; exit} } \
END {if (x<'$n') print "Fail."} ' log.txt
Output:
OK found 10
I try with travis API =>
travis logs
But with this API is not possible because I have a infinite loop (this command copy logs to logs so copy logs to logs so copy copy ...). This API is good if you read the logs of others builds only!!!
And I find a solution:
in .travis.yml file:
script:
- test/run.sh
in run.sh file:
curl -s "https://api.travis-ci.org/jobs/${TRAVIS_JOB_ID}/log.txt?deansi=true" > nonaui.log
expectation=`sed -n 's:.*<EXPECTED_RESULTS>\(.*\)</EXPECTED_RESULTS>.*:\1:p' nonaui.log | head -n 1`
nb_expectation=`sed -n ":;s/$expectation//p;t" nonaui.log | sed -n '$='`
# 3 = 1 (real) + 2 counters (Excel and CSV)
if [ "$nb_expectation" == "3" ]; then
echo "******** All counter is SUCCESS"
else
echo "******** All counter is FAIL"
exit 255
fi
exit 0

Resources