Jenkins Pipeline Conditional Option - jenkins-pipeline

I have a Jenkins pipeline that normally should run with option skipStagesAfterUnstable().
However, sometimes I need to force it to run all stages regardless of any other stages failing.
I added a boolean param in jenkins for this, and would like to make this option condition like so:
pipeline {
agent any
options {
if(env.FORCE_COMPLETE.toBoolean()){
echo "Skipping stages after unstable build."
skipStagesAfterUnstable()
} else {
echo "[!] Force complete pipeline regardless of failures"
}
}
# rest of pipeline
...
}
However, with this, I get:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 20: Expected an option # line 20, column 9.
if(env.FORCE_COMPLETE.toBoolean()){
^
Any ideas?

Related

How to abort build via shell script in Jenkins within if else condition

So I am trying my hands with Jenkins file condition within stages of build but unable to achieve the results as expected. So I want to fail a build and stop execution of next stages if failures exist in the smoke / sanity tests. This can be found only if the console has "FailedCount 0"
Here is my script:
stage('Run main tests') {
when {
expression {
// some expression
}
}
steps {
// some step which runs a test module
sh(returnStdout: true, script: '''#!/bin/bash
if [[ ${stdout} != *"FailedCount 0"* ]];then
currentBuild.result = 'ABORTED'
echo "ABORTING the JOB because of failures"
fi
'''.stripIndent())
}
}
but I am receiving this error in console with status of that stage success and the next stage also continues to execute.
durable-dde00bfa/script.sh: line 4: currentBuild.result: command not found
Could someone please help me out to see what I am doing wrong?
PS:
This is what I am asserting on within the if condition
You can't set Jenkins variables from within the shell script. If you want to simply Fail the build you can exit the shell script with exit code 1.
sh(returnStdout: true, script: '''#!/bin/bash
if [[ ${stdout} != *"FailedCount 0"* ]];then
echo "ABORTING the JOB because of failures"
exit 1
fi
'''.stripIndent())
If you wan to Abort the build you can do something like below. Get the output of the shell script and check for the Abort message.
stage('Run main tests') {
when {
expression {
// some expression
}
}
steps {
script {
// some step which runs a test module
def output = sh(returnStdout: true, script: '''#!/bin/bash
if [[ ${stdout} != *"FailedCount 0"* ]];then
echo "ABORTING the JOB because of failures"
fi
'''.stripIndent())
if (output.contains("ABORTING the JOB because of failures")) {
currentBuild.result = 'ABORTED'
error('Aborting the Build')
}
}
}
}
Update: Checking the console out and failing the build.
script {
def consoleLog = Jenkins.getInstance().getItemByFullName(env.JOB_NAME).getBuildByNumber(Integer.parseInt(env.BUILD_NUMBER)).logFile.text
if(!consoleLog.contains("FailedCount 0")){
error('Failing due to test failures')
} else {
echo "No Failures detected"
}
}

Jenkins Declarative Pipeline is not supporting shell/bash syntax

I have a shell script inside my jenkins pipeline which will call mvn. For that i have to pass variable value to mvn. The variable is not passing inside the Jenkins pipeline's shell. But when trying from local machine shell it is working fine as expected.
ARTIFACT_NAME="Sample_Artifact"
pipeline{
agent {
node{
label "${AGENT}"
}
}
stages{
stage("Setting MultiJob Properties"){
steps{
sh '''set +x
export VERSION=$(mvn -B -q -Dexec.executable=echo -Dexec.args=\${${ARTIFACT_NAME}} )
echo $VERSION
'''
}
}
}
}
Expected Process: export VERSION=$(mvn -B -q -Dexec.executable=echo -Dexec.args=${Sample_Artifact} )
Expected Output: 1.0001
ARTIFACT_NAME - I am passing it from Jenkins UI.
${${ARTIFACT_NAME}} - This variable is perfectly replace value in Freestyle jobs and it is throwing error in the Pipeline jobs.
Error Message: script.sh: 3: Bad substitution
Can Anyone please help me to resolve the issue?
As Ian wrote, you're passing the whole script as a literal (''') instead of an interpolated string ("""), so the variable name doesn't get substituted with its value:
pipeline{
agent {
node {
label AGENT
}
}
stages {
stage("Setting MultiJob Properties") {
steps {
sh """set +x
export VERSION=\$(mvn -B -q -Dexec.executable=echo -Dexec.args=\${$ARTIFACT_NAME})
echo \$VERSION"""
}
}
}
}

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.

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.

Store the console output of a build step execution in Jenkins pipeline

In my jenkins pipeline i use the "Execute shell command " to run my gradle build script.
Now i want to check if the build has failed in which case i would like to read the console output, store it in a string and publish it to a slack channel.
The code that i have tried goes as follows :
try {
for (int i = 0 ; i < noOfComponents ; i++ ){
component = compileProjectsWithPriority[i]
node {
out = sh script: "cd /home/jenkins/projects/${component} && ${gradleHome}/bin/gradle build", returnStdout: true}
}
}
catch (e){
def errorSummary = 'Build failed due to compilation error in '+"${component}"+'\n'+"${out}"
slackSend (channel: '#my_channel', color: '#FF0000', message: errorSummary)
}
However it does not even execute the shell script and also the console output is null. What is the right approach to do this.
Thanks in advance
The sh command in Jenkins pipelines may not work with shell built-ins like cd. Perhaps try using dir, as below:
node {
dir("/home/jenkins/projects/${component}") {
out = sh script: "${gradleHome}/bin/gradle build", returnStdout: true
}
}
All commands within { and } for a dir will execute with the specified directory as their working directory. This will overcome any problems that may exist with the cd shell built-in.

Resources