首页 > 解决方案 > 如何在 Jenkins 全局库中使用 sh

问题描述

我正在为托管在 github 上的 Jenkins 创建自己的全局库,为了简化一些普通任务,我想添加一个返回 GIT 标记的函数。

因此我创造了这样的东西:

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

...导致此错误:

没有方法签名:静态 com.stevnsvig.jenkins.release.ReleaseUtil.sh()

所以我有两个问题:

  1. sh()导入Jenkins 的 groovy 风格显然已经导入的库的解决方案是什么?(如果是这样的话)
  2. 这里的最佳做法是什么?我想知道为什么在GIT_TAG使用声明性管道时没有全局变量,这样的事情(在我看来)应该很容易。

编辑#1:

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

产生类似的错误:

没有方法签名:静态 com.stevnsvig.jenkins.release.ReleaseUtil.sh() 适用于参数类型:(java.util.LinkedHashMap) 值:[[returnStdout:true, script:git tag --sort version:refname | 尾巴-1]]

编辑#2:

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

完成,但输出为空白。运行相同的命令并pwd返回/表明未设置环境的返回值,这是有道理的,因为在 Jenkins 下运行的所有命令都设计为在管道下运行

编辑#3:

我去寻找进口。在 github 上偶然发现了 Jenkins CI 项目并开始搜索许多存储库。找到了一个有希望的pwd.groovy...并放入一个/vars包含以下内容的文件:

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}"
    }

我得到的错误是相同的变体。我想因为它的插件,定义是不同的......

hudson.remoting.ProxyException:groovy.lang.MissingMethodException:没有方法签名:静态 org.jenkinsci.plugins.workflow.steps.durable_task.ShellStep.sh() 适用...

标签: jenkinsgroovyjenkins-pipelinejenkins-shared-libraries

解决方案


选项 1) 使用 Groovyexecute运行 cmd 并获得如下输出

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

选项 2) 使用 Jenkins 管道步骤sh

需要明确一个概念:直接在 Jenkinsfile 中使用sh is global function时的上下文。sh

在您的情况下,sh在 Jenkinsfile 之外使用。为了更好地理解,我举了一个 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`
    }
  }
}

解决您的问题

// 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)
    }
  }
}

推荐阅读