从Jenkinsfile中的共享库导入类

时间:2020-03-26 06:58:25

标签: jenkins jenkins-pipeline jenkins-groovy jenkins-shared-libraries

我有一个共享库回购,其结构如下:

(root)
+- src             
|   +- com
|       +- company
|           +- DeploySteps.groovy
+- vars
|   +- MainDeploySteps.groovy

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

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

src / com / company / DeploySteps.groovy中的回购中的类具有要包含在Jenkinsfile中的方法(例如CheckoutSCM)。

DeploySteps.groovy:

def CheckoutSCM() {
    useful steps here
}

是否可以像这样在Jenkinsfile中包含此特定方法

import com.company.DeploySteps

然后像这样使用它:

CheckoutSCM('repo-here')

稍后在Jenkinsfile中?我读过documentation多次,但找不到答案,是否有可能从src文件夹中导入某些内容,而不仅是从vars中导入。

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

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

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

那么,从src文件夹到Jenkinsfile的导入类是否可能?

P.S。我可以在

中访问Jenkinsfile MainDeploySteps
MainDeploySteps {}

没有问题。

1 个答案:

答案 0 :(得分:1)

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

<块引用>

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

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

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

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

  • library 步骤返回可以分配给变量以供进一步使用的库的表示,类似于 def myLib = library identifier: ...
  • 可以使用库对象上的完全限定名称来引用类,例如 def myCls = myLib.com.mycom.mypkg.MyClass
  • 您收到的不是实际的 Groovy 类,而是一个类似于对象的代理,它只允许对底层 lass 进行有限的操作。
  • 您可以使用 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,因此即使是简单的 echo 也不起作用。一种传统的解决方法是提供 thisJenkinsfile 实例作为参数(例如,CheckoutSCM(this, 'repo-here')),然后将其分配给内部的 steps 参数(可以命名为任何名称)功能。然后,您将对 step 参数调用所有步骤调用,例如 step.echo '...'