我可以在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依赖。
任何想法都非常受欢迎...
答案 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稳定性的影响降到最低,例如,通过引入专用的管道插件来注册和加载此类依赖项。