我有一个Groovy库作为全局共享库提供:
package com.example
@Grab(group="org.apache.httpcomponents", module="httpclient", version="[4.5.3,)")
import org.apache.http.HttpHost
import org.apache.http.impl.client.HttpClients
class MyClass implements Serializable {
static def run() {
return HttpClients.custom()
.setProxy(new HttpHost("proxy.example.com", 3128))
.build()
}
static def debug() {
return ("""
this: ${this.classLoader.class.toString()} ${this.classLoader.hashCode().toString()}
HttpHost: ${HttpHost.class.classLoader.class.toString()} ${HttpHost.class.classLoader.hashCode()}
HttpClients: ${HttpClients.class.classLoader.class.toString()} ${HttpClients.class.classLoader.hashCode()}
""")
}
}
以及使用此库的Jenkins脚本管道作业:
@Library('example') _
node {
echo "${com.example.MyClass.debug()}"
com.example.MyClass.run()
}
当作业运行时,我从 debug()
获得以下输出,然后是 run()
的错误:
this: class org.jenkinsci.plugins.workflow.cps.CpsGroovyShell$CleanGroovyClassLoader 765101363
HttpHost: class hudson.ClassicPluginStrategy$AntClassLoader2 804623541
HttpClients: class hudson.ClassicPluginStrategy$AntClassLoader2 1870591909
hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: org.apache.http.impl.client.HttpClientBuilder.setProxy() is applicable for argument types: (org.apache.http.HttpHost) values: [http://proxy.example.com:3128]
Possible solutions: setProxy(org.apache.http.HttpHost)
The following classes appear as argument class and as parameter class, but are defined by different class loader
我很清楚,一些Jenkins插件已经依赖于httpcomponents,以下似乎是正确的:
-
我的
@Grab
注释导致下载所请求的httpclient版本(如~/.groovy/grapes
中所述) . -
但是,Groovy库没有加载或使用该版本,但是某些其他版本是某些Jenkins插件的依赖项 .
-
而且,更令人讨厌的是,
HttpHost
和HttpClients
正在从不同的类加载器加载,因此我甚至无法使用插件's version that leaked into my Groovy code'的类加载器 .
版本
- 詹金斯:2.20
插件版本
-
Groovy:2.0
-
管道:2.5
-
管道:Groovy:2.30
-
管道:共享Groovy库:2.8
有没有办法在与Jenkins插件隔离的类加载器中运行我的Groovy? Jenkins和Groovy如何共享库代码来组织类加载器?这种类型的泄漏是否是故意插入的?
这是一个错误还是我做错了什么?我意识到我是詹金斯背后的几个版本,所以这是尝试的一件事 .
除非我很幸运能够拥有其他插件没有的依赖关系,或者很幸运能够与类加载器碰巧找到的任何版本兼容,因此系统无法使用 .
1 回答
当库限定为文件夹时,
@Grab
不起作用 . 只有在全局设置中配置库时,才能在库中使用@Grab
. 这是故意的,而不是詹金斯根据plugin structure documentation的错误 .文档继续说:
就个人而言,在尝试上述操作之前,我会将Jenkins(和Pipelines)升级到最新版本 .