【问题标题】:How to invoke bash functions defined in a resource file from a Jenkins pipeline Groovy script?如何从 Jenkins 管道 Groovy 脚本调用资源文件中定义的 bash 函数?
【发布时间】:2017-03-05 22:47:23
【问题描述】:

我们正在使用 Pipeline Shared Libraries 插件来分解我们不同 Jenkins 流水线共有的代码。

From its documentation,它为非 Groovy 文件提供了一个 resources 顶级文件夹。由于我们依赖不同的 bash 函数,我们希望将它们托管在单独的 .sh 文件中(因此它们也可以被 Jenkins 以外的其他进程使用)。 相同的文档告诉我们使用libraryResource 步骤来加载这些资源文件。我们可以在我们的 Groovy 脚本中成功调用此方法,并将我们的资源文件名作为参数 (function.sh)。但是从这里开始,我们无法找到一种方法来从同一个 Groovy 脚本调用 function.sh 中定义的 foofoo 函数。

sh "foofoo"  #error: foofoo is not defined

我们也尝试先这样获取它:

sh "source function.sh && foofoo"

但它在source 步骤失败,说明找不到function.sh

调用function.sh中定义的bash函数的正确过程是什么

【问题讨论】:

    标签: bash jenkins groovy jenkins-pipeline


    【解决方案1】:

    根据documentation

    外部库可以从资源/目录加载附加文件 使用 libraryResource 步骤。参数是一个相对路径名, 类似于 Java 资源加载:

    def request = libraryResource 'com/mycorp/pipeline/somelib/request.json'
    

    文件以字符串形式加载,适合传递给某些 API 或使用 writeFile 保存到工作区。

    建议使用独特的包结构,这样您就不会 不小心与另一个库发生冲突。

    我认为以下方法会起作用

    def functions = libraryResource 'com/mycorp/pipeline/somelib/functions.sh'
    writeFile file: 'functions.sh', text: functions
    sh "source function.sh && foofoo"
    

    【讨论】:

    • 当您有一个要加载的脚本列表但既不知道文件数量也不知道文件名时该怎么办(人们可能会添加资源并且在管道内部我必须加载所有这些脚本)
    • 荒谬的是,您不能直接使用该文件,但需要创建该文件的副本。
    • 是否需要使用 Java 风格的路径?通过仅指定相对于“资源”目录的文件名似乎可以正常工作:libraryResource 'functions.sh'
    【解决方案2】:

    由于您使用的是 Jenkins Pipelines V2,因此最好为此创建一个共享库。下面的代码将起作用。除了写入文件,您还需要为文件提供执行权限:

    def scriptContent = libraryResource "com/corp/pipeline/scripts/${scriptName}"
    writeFile file: "${scriptName}", text: scriptContent
    sh "chmod +x ${scriptName}"
    

    希望这会有所帮助!

    【讨论】:

      【解决方案3】:

      所有先前的答案都是糟糕的解决方案,因为脚本在传输时被解析为文本文件,这会破坏它。

      引号等被弄乱了,它试图替换变量。

      需要逐字转移。

      唯一的解决方案是将脚本存储在文件服务器上,下载并运行它,例如:

      sh """
          wget http://some server/path../yourscript.sh
          chmod a+x yourscript.sh
         """
      

      ...或直接从 repo 中签出脚本并在本地使用,如下所示:

      withCredentials([usernamePassword(
          credentialsId: <git access credentials>,
          usernameVariable: 'username',
          passwordVariable: 'password'
      )])
      {
          sh  """
              git clone http://$username:$password@<your git server>/<shared library repo>.git gittemp
              cd gittemp
              git checkout <the branch in the shared library>
              cd ..
              mv -vf gittemp/<path to file>/yourscript.sh ./
          """
      }
      

      ...然后稍后运行您的脚本:

      sh "./yourscript.sh ...."
      

      【讨论】:

      【解决方案4】:

      在 sh 步骤开始时使用 bash shebang (#!/bin/bash) 告诉 Jenkins 使用 bash,然后像在 bash 中一样加载你的库,例如:

      sh '''#!/bin/bash
            . path/to/shared_lib.bash
             myfunc $myarg
          '''
      

      请注意,path/to/shared_lib.bash 已在您的 repo 中进行检查,以使其正常工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-05-14
        • 1970-01-01
        • 1970-01-01
        • 2018-05-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多