Hudson插件开发-实例分析
现在大概知道了Hudson的扩展点机制,我们就以Alireport为例进一步说明:
整体设计思路
该插件要实现的功能是将TestNG产生的报告以页面的形式展现出来。整体数据流如图:
插件主要过程有TestNG报告结果备份(Alireport Copy),以做版本化管理,并解决分布式运行方式问题。将TestNG的XML格式报告转换为HTML形式(Alireport XSLT)。针对用户选择的某次Build,展现该Build链接(Alireport URL Config)。
Hudson扩展点选择:这个插件,是一个有报告展现功能的插件。所以Hudson扩展点的选择应该与FindBugs,CheckStyle等相同,即选择Hudson的Publisher扩展点。
TestNG结果复制:因为TestNG的每次结果都产生在workspace中。要将结果保存下来必须将结果复制备份。结合Hudson能够保存多次Builds的特点,所以将TestNG产生的结果保存到builds中是比较好的选择。该数据的保存使用了如下接口:
build.getWorkspace().copyRecursiveTo(String condition,FilePath toPath)
该接口具有Channel特性,也就是可以通过Channel来传输位于其它分布式机器上的数据。
TestNG结果转换:这部分是将TestNG-XSLT-Maven插件集成到了Hudson插件中。
URL生成:这一部分主要是想办法让生成的HTML结果展现出来。因为在build里面是无法直接通过Web浏览器访问到的,而Hudson中有一个专门让用户放置文件的地方,即userContent目录。将HTML文件放到该目录下就能直接通过浏览器访问,每次用户点击某次build之后,Alireport要做的事是将该次HTML复制到userContent下。在Linux下面则只创建链接符。
代码修改
ReportPublisher.java
[code lang="java"]
@Override
// 重载perform
public final boolean perform(final AbstractBuild build, final Launcher launcher,
final BuildListener listener) throws InterruptedException,
IOException {
if (canContinue(build.getResult())) {
PluginLogger logger = new PluginLogger(listener.getLogger(), pluginName);
try {
String workSpacePath = build.getWorkspace().toURI().getPath() + xsltpath;
String rootDir = build.getRootDir() + "/" + copytopath;
String xsltCopyToDir = rootDir + "/xslt-files";
File copyToFile = new File(xsltCopyToDir);
boolean bMkFile = copyToFile.mkdirs();
// 将文件从workspace 中复制到每次builds中
int fileNumber = build.getWorkspace().copyRecursiveTo(xsltpath,
new FilePath(copyToFile));
logger.log("copy " + fileNumber + " files from " + workSpacePath + " to "
+ xsltCopyToDir);
// 没有复制任何文件时
if (fileNumber 0, build.number));
} catch (Exception exception) {
logger.log(exception);
return true;
}
}
return true;
}
[/code]
hudson.plugin.alireport.ReportPublisher/config.jelly 定义界面,为ReportPublisher传入参数,这里使用了Stapler的功能
ReportResultAction.java 继承了Action
[code lang="java"]
// 显示的名子"Alireport"
public String getDisplayName() {
String retString = Messages.Alireport_Publisher_Name();
return retString;
}
// 显示名子的链接地址,这里不做链接,具体链接需要计算
public String getUrlName() {
return null;
}
// 显示的图标路径
/** {@inheritDoc} */
public String getIconFileName() {
String str = getDescriptor().getIconUrl();
return str;
}
protected PluginDescriptor getDescriptor() {
return ReportPublisher.REPORT_DESCRIPTOR;
}
// 这个是要被显示到页面上的,见config.jelly
public String getSummary() {
boolean hasCoverage = CoverageReportUtil.checkEmmaFileExist(hudsonWorkUrl, jobName);
return CoverageResultSummary.createSummary(jobName, hasCoverage, "/emma/index.html");
}
[/code]
hudson.plugin.alireport.ReportResultAction/summary.jelly
通过Stapler机制调用getSummary