Jenkins pipe sh does not seem to respect the pipe in the shell team

I am using the Jenkins file in the pipeline version 2.32.2.

For various reasons, I want to extract the version string from pom. I was hoping that I would not have to add the maven support plugin and use the evaluation.

I quickly came up with a little sed expression to get it out of pom, which uses pipes and runs on the command line in the jenkins workspace on the executor.

$ sed -n '/<version>/,/<version/p' pom.xml | head -1 | sed 's/[[:blank:]]*<\/*version>//g' 1.0.0-SNAPSHOT

It can probably be optimized, but I want to understand why the pipeline seems to fail when using shed commands. I played with various string formats, and currently I am using slashy string in dollars.

The pipeline step is as follows to provide easy command line output:

 script { def ver_script = $/sed -n '/<version>/,/<version/p' pom.xml | head -1 | sed 's/[[:blank:]]*<\/*version>//g'/$ echo "${ver_script}" POM_VERSION = sh(script: "${ver_script}", returnStdout: true) echo "${POM_VERSION}" } 

When running jenkins in the pipeline, I get the following console output, where it seems to separate the commands to be transferred into separate commands:

 [Pipeline] script [Pipeline] { [Pipeline] echo sed -n '/<version>/,/<version/p' pom.xml | head -1 | sed 's/[[:blank:]]*<\/*version>//g' [Pipeline] sh [FRA-198-versioned-artifacts-44SD6DBQOGOI54UEF7NYE4ECARE7RMF7VQYXDPBVFOHS5CMSTFLA] Running shell script + sed -n /<version>/,/<version/p pom.xml + head -1 + sed s/[[:blank:]]*<\/*version>//g sed: couldn't write 89 items to stdout: Broken pipe [Pipeline] } [Pipeline] // script 

Is there any guide on the proper use of commands with channels in a jenkins file?

+13
source share
6 answers

I finally thought about it and realized that pipe substrings are probably causing the problem. I know some of the evils of eval, but I ended up tricking this into eval:

 script { def ver_script = $/eval "sed -n '/<version>/,/<version/p' pom.xml | head -1 | sed 's/[[:blank:]]*<\/*version>//g'"/$ echo "${ver_script}" POM_VERSION = sh(script: "${ver_script}", returnStdout: true) echo "${POM_VERSION}" } 
+7
source

If your environment allows this, I found a simple solution to this problem - put your script containing the channels in a file and then run it with sh, for example:

script.sh :

 #!/bin/sh kubectl exec --container bla -i $(kubectl get pods | awk '/foo-/{ print $1 }') -- php /code/dostuff 

Jenkinsfile :

 stage('Run script with pipes') { steps { sh "./script.sh" } } 
+4
source

I am also struggling with using a pipe inside my jenkins project, but as a side note, if you want an easy way to extract the version of maven pom, here is very clean, which I found in another post, and that I am using:

 stage('Preparation') { version = getVersion() print "version : " + version } def getVersion() { def matcher = readFile('pom.xml') =~ '<version>(.+)</version>' matcher ? matcher[0][1] : null } 

gives you:

 [Pipeline] echo releaseVersion : 0.1.24 [Pipeline] sh 
0
source

plug-utility-steps now includes readMavenPom , which allows you to access the version as follows:

 version = readMavenPom.getVersion() 
0
source

So none of the above worked for me using the Jenkinsfile scripting syntax with Groovy. However, I was able to get it to work. The type of quotes you use is important. In the example below, I am trying to get the latest git tag from GitHub.

 ... stage("Get latest git tag") { if (env.CHANGE_BRANCH == 'master') { sh 'git fetch --tags' TAGGED_COMMIT = sh(script: 'git rev-list --branches=master --tags --max-count=1', returnStdout: true).trim() LATEST_TAG = sh(script: 'git describe --abbrev=0 --tags ${TAGGED_COMMIT}', returnStdout: true).trim() VERSION_NUMBER = sh(script: "echo ${LATEST_TAG} | cut -d 'v' -f 2", returnStdout: true).trim() echo "VERSION_NUMBER: ${VERSION_NUMBER}" sh 'echo "VERSION_NUMBER: ${VERSION_NUMBER}"' } } ... 

Note how shell execution for LATEST_TAG works as LATEST_TAG (variable assignment for v2.1.0 ). If we tried to assign VERSION_NUMBER to the same thing (with single quotes), that would NOT work - pipe would ruin everything. Instead, we enclose the script in double quotation marks.

The first echo prints VERSION_NUMBER: 2.1.0 , and the second prints VERSION_NUMBER: If you want VERSION_NUMBER be available in shell commands, you must assign the output of the shell command to env.VERSION_NUMBER , as shown below:

 ... stage("Get latest git tag") { if (env.CHANGE_BRANCH == 'master') { sh 'git fetch --tags' TAGGED_COMMIT = sh(script: 'git rev-list --branches=master --tags --max-count=1', returnStdout: true).trim() LATEST_TAG = sh(script: 'git describe --abbrev=0 --tags ${TAGGED_COMMIT}', returnStdout: true).trim() env.VERSION_NUMBER = sh(script: "echo ${LATEST_TAG} | cut -d 'v' -f 2", returnStdout: true).trim() echo "VERSION_NUMBER: ${VERSION_NUMBER}" sh 'echo "VERSION_NUMBER: ${VERSION_NUMBER}"' } } ... 

The first echo prints VERSION_NUMBER: 2.1.0 , and the second prints VERSION_NUMBER: 2.1.0 .

0
source

I know such a late answer, but whoever you need a solution without eval can use /bin/bash -c "script" to make a pipe

 script { POM_VERSION = sh(script: "/bin/bash -c 'sed -n \'/<version>/,/<version/p\' pom.xml | head -1 | sed \'s/[[:blank:]]*<\/*version>//g\'\''", returnStdout: true) echo "${POM_VERSION}" } 

The only problem with this method is hellish escape , but our boy will handle pipes /bin/bash -c .

0
source

Source: https://habr.com/ru/post/1015423/


All Articles