如何在沙盒管道脚本中从Artifactory将Jenkins配置为@Grab依赖项

时间:2019-11-07 16:31:23

标签: jenkins-pipeline jenkins-groovy

我可以在Jenkins管道脚本中以沙箱和非沙箱模式使用@Grab注释。我的问题是,默认情况下依赖于Maven中央存储库解决了依赖关系,但我需要针对我们的Artifactory解决它们。为了演示这个问题,这里有简单的管道脚本:

//@Grab(group = 'my.compay', module='my-module-name', version='1.0.0-SNAPSHOT')
//import my.company.MyFancyClass
@Grab('com.google.guava:guava:23.0')
import com.google.common.base.Joiner

pipeline {
    agent any
    stages {
        stage('Grape Test') {
            steps {
                echo "Joiner: ${Joiner.class}"
                // echo "MyFancyClass: ${MyFancyClass.class}"
            }
        }
    }
}

按原样运行脚本时,我将在输出中看到该类的完全限定名称。但是,当我取消注释与公司工件脚本中公开的依赖项相关的注释行时,失败的原因如下:

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 2: unable to resolve class my.company.MyFancyClass
 @ line 1, column 1.
   @Grab(group = 'my.company', module='my-module-name', version='1.0.0-SNAPSHOT')

1 error

经过调查,我发现@Grab使用了Groovy特有的名称为Grape的东西,描述为here。提及的文档描述了如何使用文件〜/ .groovy / grapeConfig.xml中的ivy设置将Grape配置为使用自己的存储库。我找到了解决方案并将其用于具有以下内容的常规Groovy代码:

<ivysettings>
<settings defaultResolver="downloadGrapes"/>
<credentials host="localhost" realm="Artifactory Realm" username="USERNAME" passwd="PASSWORD"/>
<resolvers>
  <chain name="downloadGrapes" returnFirst="true">
    <filesystem name="cachedGrapes">
      <ivy pattern="${user.home}/.groovy/grapes/[organisation]/[module]/ivy-[revision].xml"/>
      <artifact pattern="${user.home}/.groovy/grapes/[organisation]/[module]/[type]s/[artifact]-[revision](-[classifier]).[ext]"/>
    </filesystem>
    <ibiblio name="localm2" root="file:${user.home}/.m2/repository/" checkmodified="true" changingPattern=".*" changingMatcher="regexp" m2compatible="true"/>

    <ibiblio name="maven-release" m2compatible="true" root="http://artifactory:8081/artifactory/maven-release"/>
    <ibiblio name="maven-snapshot" m2compatible="true" root="http://artifactory:8081/artifactory/maven-snapshot"/>
    <!-- todo add 'endorsed groovy extensions' resolver here -->
    <ibiblio name="jcenter" root="https://jcenter.bintray.com/" m2compatible="true"/>
    <ibiblio name="ibiblio" m2compatible="true"/>
  </chain>
</resolvers>
</ivysettings>

不幸的是,这个常春藤配置文件仅部分解决了我的问题,并且仅根据常规Groovy代码(与从CLI调用grape命令相同)才能使Grapes正常工作。

我不知道Jenkins如何使用Groovy / Grapes,但是它显然忽略了此文件的默认位置。我阅读了一些Ivy文档,发现可以使用属性自定义一些Ivy设置,例如配置文件位置。这就是为什么我试图通过使用以下命令从CLI运行Jenkins使其有效使用我的配置的原因:

java -Divy.settings.file=%USERPROFILE%\.groovy\grapeConfig.xml -jar jenkins.war --httpPort=8888

这确实有效,但令我惊讶的只是部分!仅当我为管道脚本关闭沙箱模式时,它才起作用。如果我将其打开,我将再次只能从maven Central获得@Grab依赖。

任何想法都非常受欢迎...

1 个答案:

答案 0 :(得分:1)

由于我没有收到任何答复,因此我进一步进行了调查,并得出了有趣的结论。首先,让我们看一下修改后的管道脚本:

@Grab('com.google.guava:guava:23.0')
import com.google.common.base.Joiner

pipeline {
    agent any
    stages {
        stage('Grape Test') {
            steps {
                echo "Joiner: ${Joiner.class}"
                 script {
                    Joiner.class.getClassLoader().getURLs().each { url ->
                        println url.toExternalForm()
                    }
                }
           }
        }
    }
}

我在沙盒模式下运行了此脚本,其中似乎可以从Maven Central满足对Guava的依赖。令人惊讶的是,我发现Joiner是从其他地方获取的,如缩短的输出所示:

...

[Pipeline] echo
Joiner: class com.google.common.base.Joiner

...

[Pipeline] echo
file:/C:/Users/mrohac/.jenkins/war/WEB-INF/lib/guava-11.0.1.jar

...

因此,此测试证明@Grab在导入工作并从类路径加载类时被默默忽略在沙箱模式下。得出的结论是,在管道脚本中使用Java编写的专有代码的唯一方法是将相关的依赖关系放在类路径上。

因此,在管道脚本中启用自定义Java代码的结论是将相关的依赖项放在了classpath上。作为詹金斯(Jenkins)的新手,对我来说值得怀疑的是,实现这一目标的最佳方法是什么。无论如何,我可以确认将依赖项置于~/.jenkins/war/WEB-INF/lib/可以有效地在管道脚本中使用所需的类。

当然,这可能意味着出现了新的问题,尤其是与Jenkins的整体稳定性有关的问题,此类问题可能会因类路径冲突而受到损害。无论如何,我希望可以使用自定义Java代码扩展管道脚本,同时将对Jenkins稳定性的影响降到最低,例如,通过引入专用的管道插件来注册和加载此类依赖项。