JoSSte
JoSSte

Reputation: 3372

How do I use sh in Jenkins Global library

I am creating my own global library for Jenkins, which I have hosted on github, and to simplify some run-of-the-mill tasks, I wanted to add a function that returns the GIT tag.

Therefore I created something like this:

    class Myclass{
      static String getGitTag() {
        return "${sh(returnStdout: true, script: 'git tag --sort version:refname | tail -1').trim()}"
      }
    }

... which results in this error:

No signature of method: static com.stevnsvig.jenkins.release.ReleaseUtil.sh()

So I'm left with two questions:

  1. Is the solution to import the sh() library that Jenkins' groovy flavor obviously already has imported? (and if so how)
  2. What is the best practice here? I am wondering why there isn't a GIT_TAG global variable when you use declarative pipelines, and something like this should (in my opinion) be easy as pie.

EDIT #1:

    static String getGitTag() {
        stdout = script.sh(script: "git tag --sort version:refname | tail -1", returnStdout: true)
        return stdout.trim()
    }

produces a similar error:

No signature of method: static com.stevnsvig.jenkins.release.ReleaseUtil.sh() is applicable for argument types: (java.util.LinkedHashMap) values: [[returnStdout:true, script:git tag --sort version:refname | tail -1]]

EDIT #2:

   static String getGitTag() {
        def stdout = "git tag --sort version:refname | tail -1".execute()
        return stdout.in.text
    }

completes, but the output is blank. Running the same command with pwd returns / which indicaes that the environment is not set, which makes sense, since all the commands running under Jenkins are designed to rununder pipelines

EDIT #3:

I went hunting for the import. Stumbled across the Jenkins CI project on github and started searching the many repositories. Found a promising one... and put a file called pwd.groovy in /vars with this content:

import org.jenkinsci.plugins.workflow.steps.durable_task.ShellStep


    static String getPWD() {
        def ret = ShellStep.sh(returnStdout: true, script: "git tag --sort version:refname | tail -1").trim()
        echo "currently in ${ret}"
    }

The error I got is a variation of the same. I guess since itsa plugin, the definition is different...

hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: static org.jenkinsci.plugins.workflow.steps.durable_task.ShellStep.sh() is applicable ...

Upvotes: 3

Views: 5087

Answers (1)

yong
yong

Reputation: 13722

Option 1) Use Groovy execute to run cmd and get its output as below

tag = "git tag --sort version:refname | tail -1".execute().text

Option 2) Use Jenkins pipeline step sh.

One concept need to get clear: the context of sh is global function is when sh used directly inside Jenkinsfile.

In your case, sh is used outside the Jenkinsfile. To make better understand I give an example Jenkinsfile.

pipeline {
 
  stages('foo') {
    steps {
       sh 'pwd' 
       // In above sh step, there is an implicit `this` which represents the 
       // global object for Jenkinsfile, you can image  sh 'pwd'  to this.sh 'pwd'
       // 
       // Thus if you want to use `sh` outside Jenkinsfile, you must pass down the
       // implicit `this` into the file where you used `sh`
    }
  }
}

To address your issue

// ReleaseUtil.groovy

static String getGitTag(steps) {
   // here `steps` is the global object for Jenkinsfile
   // you can use other pipeline step here by `steps`

   steps.echo 'test use pipeline echo outside Jenkinsfile'

   steps.withCredentials([steps.string(credentialsId: 'git_hub_auth', variable: 'GIT_AUTH_TOKEN')]) {
      steps.echo '....'
      steps.sh '....'
   }

   
   return  steps.sh(returnStdout: true, script:"git tag --sort version:refname | tail -1").trim()
}
// Jenkinsfile

import com.stevnsvig.jenkins.release.ReleaseUtil

pipeline {
 
  stages('foo') {
    steps {
       ReleaseUtil.getGitTag(this)
    }
  }
}

Upvotes: 6

Related Questions