Jenkins pipeline sh does not seem to respect pipe in shell command

前端 未结 6 1257
清歌不尽
清歌不尽 2020-12-15 20:29

I am using a Jenkinsfile in a pipeline on version 2.32.2.

For various reasons I want to extract the version string from the pom. I was hoping I wouldn\'t have to a

相关标签:
6条回答
  • 2020-12-15 20:53

    I am also struggling with the usage of pipe inside my jenkins pipeline but as a side note, if you want a simple way to extract the version of a maven pom, here's a very clean one I found in another post and that I'm 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 讨论(0)
  • 2020-12-15 21:04

    The pipeline-utility-steps plugin nowadays includes a readMavenPom step, which allows to access the version as follows:

    version = readMavenPom.getVersion()
    
    0 讨论(0)
  • 2020-12-15 21:10

    So nothing detailed above worked for me using the scripted Jenkinsfile syntax with Groovy. I was able to get it working, however. The type of quotations you use are important. In the example below, I am trying to fetch 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}"'
      }
    }
    ...
    

    Notice how the shell execution to assign LATEST_TAG works as expected (assigning the variable to v2.1.0). If we were to try the same thing (with single quotes) to assign VERSION_NUMBER, it would NOT work - the pipe messes everything up. Instead, we wrap the script in double quotes.

    The first echo prints VERSION_NUMBER: 2.1.0 but the second prints VERSION_NUMBER:. If you want VERSION_NUMBER to be available in the shell commands, you have to 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 讨论(0)
  • 2020-12-15 21:11

    If your environment allows it, I've found a simple solution to this problem to be to place your script containing pipes into a file, and then run that with sh, like so:

    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"
      }
    }
    
    0 讨论(0)
  • 2020-12-15 21:13

    I know this kind of late answer, but whoever you who needs the solution without eval you can use /bin/bash -c "script" to make pipe works

    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 yet this way the subshell of pipe will be handled by our boy /bin/bash -c

    0 讨论(0)
  • 2020-12-15 21:14

    I finally put some thought into it and realized that pipe subshells are probably causing the issue. I know some of the evils of eval but I ended up wrappping this in an 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}"
    }   
    
    0 讨论(0)
提交回复
热议问题