How to modify xml elements from an xml file in jenkins - jenkins

I have an issue with my pipeline. I have an XML file in my project repo and I will like to read this file and change values after my checkout stage.
verNum.xml
<Version>1.0.0 </Version>
and my jenkinsfile
node {
stage ('checkout') {
.......
}
stage ('readfile') {
readFile("verNum.xml")
}
}
I would increment the last digit of the version number with my build number. say something like this 1.0.${BUILD_NUMBER}.
Your help is highly welcomed.

You can use linux cmd: sed to replace text.
sh '''
sed -r -i 's/(<Version>1.0.)[0-9]*(.*)/\\1'$BUILD_NUMBER'\\2/' verNum.xml
'''

Related

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

Calling functions in jenkinsfile with variables

I need some help in calling a function in Jenkinsfile along with a variable.
I have created a bash function to copy certain test results from jenkins slave to Jenkins master's userContent directory.
I want to use this function across diff jobs. Different jobs might have different report path, instead of hardcoding the path inside the function i want to use a variable in jenkinsfile to pass along with the function.
Here is my function:
def call() {
sh '''
mkdir -p $JOB_NAME
foldername="$BUILD_NUMBER.$(date '+%d-%m-%Y')"
echo ${foldername}
mkdir -p $JOB_NAME/${foldername}
pwd
reportPath=""
dest="./$JOB_NAME/${foldername}"
cp -R ${reportPath}/*.xml ${dest}
scp -r $JOB_NAME jenkins#master_ip:/var/lib/jenkins/userContent/
'''
}
How do i call the function in jenkinsfile and have a variable with report path?
I guess you want to copy Jenkins Slave artifact to master. You can use following plugin https://wiki.jenkins.io/display/JENKINS/Copy+Artifact+Plugin
You can use following method for declarative pipeline jobs:
stages {
stage('Copy Archive') {
steps {
script {
step ([$class: 'CopyArtifact',
projectName: 'Create_archive',
filter: "packages/infra*.zip",
target: 'Infra']);
}
}
}

Syntax error while using backslash in Jenkinsfile

I try to make simple pipeline on Jenkins to remove files from few directories time to time. I decided not to create python script with Jenkinsfile as new project, instead of it I try to define new pipeline script in Jenkins job.
pipeline {
agent any
stages {
stage('Check virtualenv') {
steps {
sh """
rm -r /mnt/x/some/directory/Problem\ 1.0/path
"""
}
}
}
}
And I got an error WorkflowScript: 4: unexpected char: '\'. How can I use path with whitespace on it without using backslash? Any other ideas how define path?
The '\' character is a special character in Groovy. If you tried to compile this kind of code with the normal Groovy compiler, it would give you a better error message. The easiest way to handle it would be to escape it:
"""
rm -r /mnt/x/some/directory/Problem\\ 1.0/path
"""
You can modify the shell command as follows:
sh """
rm -r /mnt/x/some/directory/Problem""" + """ 1.0/path"""
Provide space before 1.0 as required. Hope this helps.

Jenkins Pipeline Utility Steps - zip zipFile

I am trying to zip the folders which are created as output of my jenkins pipeline job using pipeline script. By googling i came to know the Jenkins
Pipeline Utility Steps - zip zipFile
https://jenkins.io/doc/pipeline/steps/pipeline-utility-steps/#code-zip-code-create-zip-file to zip folders/files but could not get exact pipeline syntax to zip.
In my job workspace, I have a folder by name 'Test' which has 2 sub folders as 'Test1', 'Test2'. Each sub folder will have .dll files. So, I would like to zip entire 'Test' folder with all subfolder.
node(Jenkinks_1)
{
echo "ZIP"
zip zipFile: 'Test.zip', dir:'C:\\workspace\\Build_Sample\\Test'
echo "END - ZIP"
}
Below are the Console Output from Jenkins:
Started by user XXXXX
[Pipeline] node
Running on Jenkinks_1 in C:\workspace\Build_Sample
[Pipeline] {
[Pipeline] echo
ZIP
[Pipeline] echo
END - ZIP
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
Looking for some guidance to zip the folders using pipeline syntax. Appreciate your inputs.
I wanted to zip some files as output of my jenkins pipeline job
First, try the same operation in stages and step, as in here:
pipeline {
agent any
stages {
stage ('push artifact') {
steps {
sh 'mkdir archive'
sh 'echo test > archive/test.txt'
zip zipFile: 'test.zip', archive: false, dir: 'archive'
archiveArtifacts artifacts: 'test.zip', fingerprint: true
}
}
...
}
It uses archiveArtifacts to record the result.
If using an absolute path does now work, try a relative one ('..')
As seen by the OP Sri, zip zipFile is part of, and requires the JENKINS Pipeline Utility Steps Plugin.
See "Implemented Steps".
Regarding the syntax to be used for multi-criteria file selection, NicolasW notes in the comments that the documentation is vague: "use glob ant-style syntax"...
He got it to work though, with a basic coma separated syntax.
E.g.
zip zipFile: 'test.zip', archive: false, glob: 'config-/**/,scripts/**/*.*
But, as noted by Tanvir in the comments, issue 44078 means you need to replace zip by:
script{ zip zipFile: 'test.zip', archive: false, dir: 'archive' }
Meaning you need to use a script block.
Was able to Zip after installing the Pipeline Utility Steps plugin.
I came across this because zip was ... not installed on the host.
Reminder to self : If you need zip, install it first.
sudo yum install zip
you can just use sh (jenkins server need install zip);
sh '''
zip -r algo.zip algo
'''
pipeline script like this
node {
stage('Clean'){
cleanWs()
}
stage('Checkout') {
git branch: 'develop', url: 'ssh://user#ip:29418/prj.git'
}
stage('Zip') {
dir('algo-python') {
sh '''
zip -r algo.zip algo
'''
}
}
stage('Upload zip'){
dir('algo-python') {
sh '''
source /etc/profile
export HADOOP_USER_NAME=dev
hdfs dfs -put -f algo.zip /user/dev/zipfile/
'''
}
}
}

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