从 Jenkinsfile 中的共享库导入类

Mik*_* P. 5 jenkins jenkins-groovy jenkins-pipeline jenkins-shared-libraries

我有一个具有以下结构的共享库存储库:

(root)
+- src             
|   +- com
|       +- company
|           +- DeploySteps.groovy
+- vars
|   +- MainDeploySteps.groovy
Run Code Online (Sandbox Code Playgroud)

该库通过 Jenkinsfile 导入到作业中,如下所示:

library identifier: 'jenkinslib@master', retriever: modernSCM(
     [$class       : 'GitSCMSource',
      remote       : 'git@url.to.git:jenkinslib.git',
      credentialsId: 'jenkins-credentials'])
Run Code Online (Sandbox Code Playgroud)

src/com/company/DeploySteps.groovy 中的存储库中的类有一个方法(例如 CheckoutSCM),我希望将其包含在 Jenkinsfile 中。

部署步骤.groovy:

def CheckoutSCM() {
    useful steps here
}
Run Code Online (Sandbox Code Playgroud)

是否有可能在 Jenkinsfile 中包含此特定方法,例如

import com.company.DeploySteps
Run Code Online (Sandbox Code Playgroud)

然后像这样使用它:

CheckoutSCM('repo-here')
Run Code Online (Sandbox Code Playgroud)

稍后在 Jenkinsfile 中?我多次阅读文档src,但没有找到答案是否可以从文件夹导入某些内容,而不仅仅是从vars.

为什么我要问,因为现在当 import:import com.company.DeployUtils然后尝试调用方法时,CheckoutSCM()会在 Jenkins 控制台输出中看到错误:

java.lang.NoSuchMethodError:在步骤中找不到这样的 DSL 方法“CheckoutSCM”

下面列出了可用的方法,其中CheckoutSCM肯定没有我的方法)

那么,是否可以将类从src文件夹导入到 Jenkinsfile 中?

PS 我可以在 Jenkinsfile MainDeploySteps 中访问

MainDeploySteps {}
Run Code Online (Sandbox Code Playgroud)

不过没有任何问题。

har*_*dsv 6

我只是想添加一个答案来解决 OP 和后续评论中的几个问题。

我是否正确理解您的共享库仅公开“vars”目录中的全局变量,以将该变量包含到 Jenkinsfile 中?虽然尝试直接从“src”文件夹将其他任何内容包含到 Jenkinsfile 中并不是它的设计方式,因为“src”类旨在包含“vars”目录中的变量。

首先让我介绍一下共享库的背景知识。有两种类型,称为动态共享库(使用library步骤定义)和全局共享库(在 Jenkins 全局配置中定义并使用@Library注释访问)。两者之间的两个重要区别是:

  • 沙盒限制不适用于全局共享库中的代码,因为此类库中的代码被视为受信任(毕竟,它是由管理员全局配置的)。动态共享库的情况并非如此,因为它们是由用户定义的,因此不可信。
  • 全局共享库中的类可以在 中静态引用Jenkinsfile并作为 编译的一部分进行解析Jenkinsfile,但这对于动态共享库来说是不可能的,因为这些库是在运行时定义的,并且在编译时无法交叉检查类。

来到OP,它使用动态共享库概念,这意味着类不能被静态引用。然而,动态共享库中有一些可以利用的功能。这些详细信息可以在文档中找到,但这里是一个摘要:

  • library步骤返回库的表示形式,可以将其分配给变量以供进一步使用,例如def myLib = library identifier: ...
  • 可以使用库对象上的完全限定名称来引用类,例如def myCls = myLib.com.mycom.mypkg.MyClass
  • 您收到的不是实际的 Groovy 类,而是一个类似代理的对象,只允许对底层类进行有限的操作。
  • 您可以使用new函数实例化一个新实例,它的工作方式与运算符非常相似new。您传递的参数与传递给构造函数的参数相同,例如,myCls.new(arg1, arg2)
  • 您可以获取静态变量(尽管无法设置它)或使用代理对象调用静态方法,就像它是真正的类一样。如果您无论如何都要实例化一个对象new,那么您也可以通过实例访问静态成员(正常的 Groovy 语义适用)。

在这两种类型的库中,var 文件使用相同的机制公开(也称为全局变量和自定义步骤),因此使用上没有区别。此外,var 文件在库的上下文中执行,因此在 var 文件中,您不需要特殊的语法来访问类,无论它们是在全局库还是动态共享库中。

现在要回答OP中的真正问题,可以CheckoutSCM从动态共享库中调用。如果它被定义为静态函数,则可以使用调用它myLib.com.company.DeploySteps.CheckoutSCM('repo-here'),如果它被定义为非静态方法,则可以使用调用它myLib.com.company.DeploySteps.new(...).CheckoutSCM('repo-here')。然而,在这两种情况下,该类DeploySteps将无法访问步骤 API,因此即使是简单的 API 也echo无法工作。一种传统的解决方法是提供 的this实例Jenkinsfile作为参数(例如,CheckoutSCM(this, 'repo-here')),然后将其分配给steps函数内的参数(可以命名为任何名称)。然后,您将调用参数上的所有步骤调用steps,例如steps.echo '...'