About the Jenkins if else statement in a pipeline - jenkins

My Jenkins have a pipeline task name the 'if-test'.
I have a log file name the 'result.log' and it placed on this task Workspace path.
Now, I want to check this result.log file content has a word 'FAILED', then run Jenkins pipeline stage A.
And, if this result.log file content is not included the word 'FAILED', then run Jenkins pipeline stage B.
I try to use the def aa = (sh grep -i 'failed' ./result.log)....
But, I think it's the wrong statement.
Everyone who can help me to find the correct statement for that?
Thank you.

You can refer something like below, populate the details as and what required.
node{
stage ('Build'){
if (readFile('test').contains('FAILED')) {
echo "present"
}
else {
echo "absent"
}
}
}

Related

Jenkins pipeline error in handling json file

I'm newbie to Jenkins pipeline and writing a groovy script to parse a json file. However I'm facing an error which many have faced but none of the solutions worked for me. Below is my Jenkinsfile and error msg.
def envname = readJSON file: '${env.WORKSPACE}/manifest.json'
pipeline {
agent any
stages {
stage('Build') {
steps {
echo WORKSPACE
sh "ls -a ${WORKSPACE}"
}
}
}
}
[Pipeline] Start of Pipeline
[Pipeline] readJSON
[Pipeline] End of Pipeline
org.jenkinsci.plugins.workflow.steps.MissingContextVariableException:
Required context class hudson.FilePath is missing Perhaps you forgot
to surround the code with a step that provides this, such as: node at
org.jenkinsci.plugins.pipeline.utility.steps.AbstractFileOrTextStepExecution.run(AbstractFileOrTextStepExecution.java:30)
I even tried readJSON file: '${WORKSPACE}/manifest.json but that didn't work too. I'm sure the mistake is with the first line since when removing that line, there execution is successful. The docs are pretty helpful but I'm not able to track down where exactly I'm going wrong that is why posted here.
UPDATE:
I tried the following methods def envname = readJSON file: "./manifest.json" and def envname = readJSON file: "${env.WORKSPACE}/manifest.json" and even tried them defining under the steps block. Nothing worked. Below is the error msg I recieved when I defined them under step block
WorkflowScript: 5: Expected a step # line 7, column 13
def envname =
^
Below is the official syntax doc of readJson and I can see that I'm using the correct syntax only. but still doesn't work as expected.
https://www.jenkins.io/doc/pipeline/steps/pipeline-utility-steps/#readjson-read-json-from-files-in-the-workspace
'${env.WORKSPACE}/manifest.json' is interpolating the Groovy env map as a shell variable. You need to interpolate it as a Groovy variable like "${env.WORKSPACE}/manifest.json".
sh "ls -a ${WORKSPACE}" is interpolating the shell environment variable WORKSPACE as a Groovy variable. You need to interpolate it as a shell variable like sh 'ls -a ${WORKSPACE}'.
echo WORKSPACE is attempting to resolve the shell variable WORKSPACE as a first class Groovy variable expression. You need to use the Groovy env map instead like echo env.WORKSPACE.
As for the global variable indefinite type assignment on the first line: if it still throws the error above after making those fixes, then it may be due to invalid use of scripted syntax in a declarative syntax pipeline. You likely need to place it inside a step block within your pipeline in that case.
I've solved this myself with the help of "Matt Schuchard"'s below answer. I'm not sure whether this is the only way to solve but this worked for me.
pipeline {
agent any
stages {
stage('Json-Build') {
steps {
script {
def envname = readJSON file: "${env.WORKSPACE}/manifest.json"
element1 = "${envname.dev}"
echo element1
}
}
}
}
}

Jenkinsfile, prebuild script

I'm a using the jenkins pipeline. My usecase is that the developer are using a simple *.ini file that is parsed by a python script to add or remove stage within the jenkinsfile whenever they want. I don't want them to manually edit the jenkinsfile because they won't know how it works.
Expected behaviour is:
When a build is triggered I would like to first execute a python script which might write into the jenkinsfile to add/remove stage according to the *.ini file.
As far as I understand, when an event trigger a jenkins build, the first thing it does is opening the jenkinsfile. However I would like to know if it's possible to run some prebuild script before that ?
Thanks
Edit: here's a simple view of run of the pipeline (blue ocean UI)
The ini file might for example remove in the stage Compilation the step Building Plan C by removing the groovy code doing that in the jenkins file
Give an example for reference.
node {
git url: '', branch: '', credentialsId: ''
def parseStr = sh(script: 'python parser.py xxx.ini', returnStdout: true).trim()
// the python parser expect to return a JSON string like:
// {'run_stage1': false, 'run_stage2': true}
def parseObj = readJSON text: parseStr
stage('stage 1') {
if(parseObj.run_stage1) {
echo 'stage1'
...
}
}
stage('stage 1') {
if(parseObj.run_stage2) {
echo 'stage1'
....
}
}
}
Jenkins pipeline had supply apis: readJSON, readYaml, readProperties to read JSON, YAML and Properties files.
If you choose any of them to replace ini file, you can drop the python parser to make your pipeline more simple

new File("path/tmp.txt") at Jenkins node

I have a very simple pipeline which works on a master. I was reading a line in a tmp.txt which works on Jenkins (master).
stage ('Stage 1'){
node('master') {
File file1 = new File("env.Workspace/tmp.txt")
def String my_line = file1.readLines().get(0)
…
}
}
I’ve have to move the stage to other one node (slave) and it doesn’t work anymore. If there is a tmp.txt in a workspace of master – pipeline reads it. But I want to read the tmp.txt in a workspace of node, not from master!
stage ('Stage 1'){
node('Agent_1') {
File file1 = new File("env.Workspace/tmp.txt")
def String my_line = file1.readLines().get(0)
…
}
}
I've found an info that:
“File always implies a file path on the current computer”.
What does it mean? It must be possible to read a file from node..
Can anybody help there?
Do not use native Groovy/Java IO functions, but use pipeline steps instead. The reason for this is that the pipeline code itself is always executed on the master!
The correct (pseudo) code, using the readFile step, would be like:
stage ('Stage 1'){
node('Agent_1') {
def String my_line = readFile("tmp.txt")
…
}
}

Jenkins multibranch pipeline post build actions

How to define post build actions for Jenkins multi pipeline project?
There is a separate option available when you have a simple project but not for multipipeline.
To add post build steps to a Multibranch Pipeline, you need to code these steps into the finally block, an example is below:
node {
try {
stage("Checkout") {
// checkout scm
}
stage("Build & test") {
// build & Unit test
}
} catch (e) {
// fail the build if an exception is thrown
currentBuild.result = "FAILED"
throw e
} finally {
// Post build steps here
/* Success or failure, always run post build steps */
// send email
// publish test results etc etc
}
}
For most of the post-build steps you would want there are online examples of them on how to write in pipeline format. If you have any specific one please list it here
When you write a pipeline, you describe the whole flow yourself, which gives you great flexibility to do whatever you want, including running post-build steps.
You can see an example of using post-build steps in a pipeline I wrote:
https://github.com/geek-kb/Android_Pipeline/blob/master/Jenkinsfile
Example from that code:
run_in_stage('Post steps', {
sh """
# Add libCore.so files to symbols.zip
find ${cwd}/Product-CoreSDK/obj/local -name libCore.so | zip -r ${cwd}/Product/build/outputs/symbols.zip -#
# Remove unaligned apk's
rm -f ${cwd}/Product/build/outputs/apk/*-unaligned.apk
"""
})

Jenkins Pipeline - Reading previous stage log

Consider a Jenkins Pipeline with two stages, Stage A then Stage B.
In Stage B, is it possible to parse the logs of Stage A for some particular text?
Use tee to split the output to both stdout and file. Next parse the file for your text.
STAGE_A_LOG_FILE = 'stage_a.log'
pipeline {
agent any
stages {
stage('Stage A') {
steps {
script {
// tee log into file
tee(STAGE_A_LOG_FILE) {
echo 'print some Stage_A log content ...'
}
}
}
}
stage('Stage B') {
steps {
script {
// search log file for 'Stage_A'
regex = java.util.regex.Pattern.compile('some (Stage_A) log')
matcher = regex.matcher(readFile(STAGE_A_LOG_FILE))
if (matcher.find()) {
echo "found: ${matcher.group(1)}"
}
}
}
}
}
}
Pipeline output:
print some Stage_A log content ...
found: Stage_A
Finished: SUCCESS
There's been an update since July 28th !
As mentionned in this answer, as of version 2.4 of Pipeline: Nodes and Processes you can use:
def out = sh script: 'command', returnStdout: true
At least it's much more simple and clean than outputting to a file and reading the file afterwards.
What I finally did was, as suggested, to write to a file (and stdout) using tee.
sh "command | tee <filename>"
Then parse the file as needed, using readFile <filename> to read the file from the workspace.
If you want to search for the first occurrance of a pattern, you can also use manager.logContains(regexp) or manager.getLogMatcher(regexp). See my other answer for more details: https://stackoverflow.com/a/39873765/4527766

Resources