参考:https://wiki.jenkins-ci.org/display/JENKINS/Basic+guide+to+Jelly+usage+in+Jenkins
这个插件就是用来展示如何使用基于Stapler, Jelly, Groovy等技术的Jenkins UI 控件的。安装这个插件对学习Jenkins插件开发非常有用。
一个基本的jenkins插件结构包括以下几个部分:
假如已经写好一个类 src/main/java/org/myorganization/MyAction.java,要为这个类定义一个Jelly文件。
一个目录下的所有Jelly文件都跟和该目录一一对应的某个类直接关联。这个对应的类对象会绑定到jelly文件中名字为 it 的变量上,jelly文件中可以通过it变量调用类中的方法,调用代码要用一对大括号包裹,前括号前加$。形式为:${insert code here}。
例如在MyAction.java中定义了如下的方法
public String getMyString() { return "Hello Jenkins!"; }
在jelly文件中调用这个方法的示例
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form"> ${it.myString} </j:jelly>
方法名开头的get被自动去掉了,剩余部分首字母变成小写。建议使用java约定的命名方式(如getter方法都是get开头的CamelCase形式)确保Jelly能够找到正确的方法。
Jenkins中预定义对象主要有
与jelly文件直接关联的类实例
当前正在被配置的对象(在配置页面中的一个区域内),例如BuildStep。如果不是重新配置而是刚添加了一个新的实例的话这个变量为null。
Jenkins(或Hudson)实例
与instance对象所属类对应的Descriptor对象
hudson.Functions对象的实例,提供了很多非常有用的方法。
预定义URL变量
Jenkins实例的URL
JavaScript, HTML等静态webapp资源(cf. Jenkins.RESOURCE_PATH)
图标等图像资源路径 ,实际就是resURL/images
应尽可能使用resURL而不是rootURL,因为resURL允许浏览器缓存,可以提高响应速度减轻服务器压力。
只要在l:layout或l:ajax块内,这些URL就已经定义好了,也就是说在任何的Jenkins页面里都可以使用(如果页面是通过ajax加载的,需要添加l:ajax标签)。
Note that until 1.505 rootURL will be empty in the typical case of Jenkins running in development mode with no context path (http://localhost:8080/); it is used for creating server-absolute paths such as /some/path for direct links. As of 1.505 it will be /jenkins in test mode, to help remind you to use it! In the rare case that you need to pass a complete URL to an external service for some reason, use app.rootUrl instead (which takes into account “Jenkins URL” from the system /configure screen). Hyperlinks in HTML has a fuller treatment of this topic.
大多数情况下,jelly文件修改后不需要重启Jenkins服务就能看到效果。修改文件然后重新请求页面,修改后的jelly文件就会被加载了。
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form"> <f:entry title="${%Port}" field="port"> <f:textbox /> </f:entry> <f:entry title="${%Host}" field="host"> <f:textbox /> </f:entry> </j:jelly>
${%...}为国际化标记(https://wiki.jenkins-ci.org/display/JENKINS/Internationalization)。
插件可以使用src/main/resources/path/to/plugin/PluginName目录中的help-FIELD.html或help-FIELD.jelly文件。Jenkins会在对应的Filed元素后添加一个问号图标,点击图标就会将帮助文件在配置页面中内联的渲染出来。help.html或help.jelly会作为插件顶级的帮助文件。
在descriptor类中添加的doCheckFIELD方法,会被用于表单验证逻辑。示例如下:
public FormValidation doCheckPort(@QueryParameter String value) { if(looksOk(value)) return FormValidation.ok(); else return FormValidation.error("There's a problem here"); }
这个方法中可以有多个指定了具体Filed的@QueryParameter("FIELD")注解参数,同时获得多个参数值。可以表单field之间相互依赖关系的验证。更详细的内容可以查询stapler的文档。
可以使用页面元素的default属性为表单域设置默认值。即可以用字面值,也可以编程式的方式计算默认值(使用jelly预定义的变量,调用这些对象的方法)。示例如下:
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form"> <f:entry title="${%Port}" field="port"> <f:textbox default="80" /> </f:entry> <f:entry title="${%Host}" field="host"> <f:textbox default="${descriptor.defaultHost()}/> </f:entry> </j:jelly>
参考插件:https://github.com/jenkinsci/sidebar-link-plugin
如果插件用了无Descriptor的对象,如ComputerListener。可以按下面的步骤,在配置页面中增加一个插件类(Plugin的子类)可读取的文本框。
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form"> <f:section title="My Plugin"> <f:entry title="${%Port}" help="/plugin/ARTIFACT_ID_GOES_HERE/help-projectConfig.html"> <f:textbox name="port" value="${it.port}"/> </f:entry> </f:section> </j:jelly>
https://wiki.jenkins-ci.org/display/JENKINS/Hyperlinks+in+HTML
HTML中的超链接应该使用相对URL(如../foo/bar, build/5/changes)或应用相对URL(以/开头,如/job/foo/5, /manage)。但是前面不要用绝对路径(如http://jenkins/foo/1)。让浏览器将相对路径绝对化。
这条规则的原因是,经过反向代理等过程后,web应用无法知道客户端用来访问服务器的URL。但是反向代理都会保证URL中的路径部分(context path+path info)是原封不动的,使用应用内部的相对路径不会有任何影响。
在JavaEE中,URL的路径部分可分为两段,先是context path,后面跟着Path Info。例如http://server.example.com/jenkins/job/foo/5,/jenkins为context path,/job/foo/5为path info。Jenkins开发者可以控制后者。
图片,JavaScript脚本,样式表等静态资源在Jenkins运行中不会变化,应该使用静态资源前缀的URL(/static/XXXXX)访问,如/static/907dbcb0/plugin/foobar/abc.png。XXXXX部分是Jenkins为运行中的Jenkins Session持续期而生成的随机字符串。请求的路由与不带前缀的相同,但是带了前缀后头信息中会设置很长的过期时间,让浏览器使用缓存。随机数字是为了防止plugins/core更新后浏览器使用旧数据。
在Java中: Functions.getResourcePath()作为URL的前缀。在Jelly中使用resURL变量。
Functions.getResourcePath()+"/plugin/git/icons/git-32x32.png"; <img src="${resURL}/plugin/translation/flags.png" />
如果以HTTP响应以为的方式提供服务数据,需要生成绝对路径。可用Jenkins.getInstance().getRootUrl()方法,将返回管理员配置的绝对路径。这是在Jenkins实例中准确获取绝对路径的唯一方法。
通过HyperlinkNote向控制台输出中嵌入超链接时,使用/开头的URL创建便携的超链接(如果URL以/开头,就会相对于context path处理)。这样就算控制台note创建以后,Jenkins URL变了,超链接依然能正确渲染。
void foo(TaskListener listener) { listener.getLogger().println( HyperlinkNote.encodeTo("/configure","Please configure your Jenkins")); }
在Jenkins轻易地创建指向不同对象的超链接,可以查阅ModelHyperlinkNote类(http://javadoc.jenkins-ci.org/?hudson/console/ModelHyperlinkNote.html)。
如果反向代理终止了HTTPS,Jenkins无法利用HttpServletRequest#isSecure()检查传输是否安全。Jenkins.isRootUrlSecure()可以检查管理员配置的Jenkins URL是否是Https。
https://wiki.jenkins-ci.org/display/JENKINS/Jenkins+says+my+reverse+proxy+setup+is+broken
https://wiki.jenkins-ci.org/display/JENKINS/Running+Jenkins+behind+Apache
https://wiki.jenkins-ci.org/display/JENKINS/Running+Jenkins+behind+Nginx
https://wiki.jenkins-ci.org/display/JENKINS/Internationalization
properties文件默认编码为ISO-8859-1。静态资源文件编码为UTF-8。
Jenkins使用Localizer(https://java.net/projects/localizer/)生成Messages类,能够以类型安全的方式访问Message资源。src/main/resources/**/Messages.properties匹配的所以文件都会生成一个对应的Messages类。如过IDE找不到这些类,需要手动将target/generated-sources/localizer目录加入源码的根目录。返回用于显示的字符串的代码(如Descriptor.getDisplayName())可以使用Messages类获取本地化的消息。在运行时,适当的locale会被自动选择。
典型的工作流如下:
如果消息中包含单引号('),需要再用一个单引号昨晚转义('')。如果想使用英文撇号(’),可以用unicode字符 U+2019,在properties文件中写成\u2019。
${%xxxx} 标记指示stapler查找本地化资源, 如果没有找到对应资源,就原样输出xxxx。
<h1>${%Output}</h1>
要渲染出的结果:
<p>Click <a href="${obj.someMethod(a,b,c)}" >here</a></p>
foo.properties文件中内容为:
click.here.link = Click <a href="{0}" >here</a>
jelly中消息引用标记:
<p>${%click.here.link(obj.someMethod(a,b,c))}</p>
因为参数使用了的括号()包裹,所以普通文本中不能包含括号。
<h1>${%Path to file (.ipa or .apk)}</h1> 解析会出错
这种情况下可以通过拆分文本,将括号排除在{% }标记外部
<h1>${%Path to file} (${%.ipa or .apk})</h1>
多个参数之间用 , 分隔(类似方法调用)。在properties文件中按参数位置引用 {0}为第一个参数,{1}为第二个参数......(按MessageFormat解析,参考:http://docs.oracle.com/javase/6/docs/api/java/text/MessageFormat.html)
<p>${h.ifThenElse(x,"no error","error")}</p>
<p>${h.ifThenElse(x,"%no error","%error")}</p>
默认help.html为English。然后再为xx语言创建help_xx.html文件即可。
Translation Tool :命令行资源文件翻译工具(https://wiki.jenkins-ci.org/display/JENKINS/Translation+Tool)
Translation Assistance Plugin :Adds a dialog box in Jenkins to translate and send missing keys.
Stapler plugin for IntelliJ IDEA: 利用反射提取java代码中的资源到properties文件(mvn compile编译之前会显示错误)。
NetBeans plugin for Stapler
要翻译的内容
http://www.simonwiest.de/glottr/report/