近期项目中在jenkins自动构建基础上引入了findbugs进行代码检测,藉以发现项目中隐藏的一些问题。部署使用后发现一些bug是项目中不需要去修改的,众所周知在eclipse中findbugs插件是可以配置检测规则的,因此想通过一种配置方式去规避掉这些不需要的检测。然而搜索了好多资料之后,都是教如何配置插件使用的,仍然没有找到有效的方式去定义检测类型,面对一些毫无必要的bug展示在那,强迫症患者每次见到都如鲠在喉。遂决心深入看下插件的代码,找一种方式去规避这些没有必要的检测。
调整思路
通过对message.xml的跟踪,发现了在FindBugsParser类的parse方法中会对文件进行检测(调用readXml方法)获得SortedBugCollection,然后遍历bugs信息,并从message.xml中获取bug的描述信息。而readXml中调用的方法在library-2.0.4.jar中,在library包中也有检测器的配置文件:findbugs.xml,然而获取的library源码中并未有任何代码和配置文件信息,是通过依赖的方式引入的,build时会把相关文件打进jar中,直接修改检测器配置文件的方式暂时行不通了,而直接修改jar包中的xml文件打包后会导致jenkins无法读取jar中的class文件,只能放弃了。于是换了一种取巧的方式,在对bugs遍历时,通过控制bug的描述信息,对于特定描述(ShortDescription为ignore)的bug采取忽略方式达到了效果。
调整步骤
1、获取git上findbugs插件源码,以4.72为例
git地址:https://github.com/jenkinsci/findbugs-plugin/releases/tag/findbugs-4.72
2、修改FindBugsParser类parse方法,将不需要检测的类型去掉
代码如下:
/**
* Returns the parsed FindBugs analysis file. This scanner accepts files in the native FindBugs format.
*
* @param file
* the FindBugs analysis file
* @param sources
* a collection of folders to scan for source files
* @param moduleName
* name of maven module
* @param hashToMessageMapping
* mapping of hash codes to messages
* @param categories
* mapping from bug types to their categories
* @return the parsed result (stored in the module instance)
* @throws IOException
* if the file could not be parsed
* @throws DocumentException
* in case of a parser exception
*/
private Collection<FileAnnotation> parse(final InputStream file, final Collection<String> sources,
final String moduleName, final Map<String, String> hashToMessageMapping,
final Map<String, String> categories) throws IOException, DocumentException {
SortedBugCollection collection = readXml(file);
Project project = collection.getProject();
for (String sourceFolder : sources) {
project.addSourceDir(sourceFolder);
}
SourceFinder sourceFinder = new SourceFinder(project);
String actualName = extractModuleName(moduleName, project);
TreeStringBuilder stringPool = new TreeStringBuilder();
List<FileAnnotation> annotations = new ArrayList<FileAnnotation>();
Collection<BugInstance> bugs = collection.getCollection();
for (BugInstance warning : bugs) {
SourceLineAnnotation sourceLine = warning.getPrimarySourceLineAnnotation();
String message = warning.getMessage();
String type = warning.getType();
if (message.contains("TEST: Unknown")) {
message = FindBugsMessages.getInstance().getShortMessage(type, LocaleProvider.getLocale());
}
//将标记为ignore的类型忽略掉
String tempMsg = FindBugsMessages.getInstance().getShortMessage(type, LocaleProvider.getLocale());
if("ignore".equals(tempMsg)){
continue;
}
String category = categories.get(type);
if (category == null) { // alternately, only if warning.getBugPattern().getType().equals("UNKNOWN")
category = warning.getBugPattern().getCategory();
}
Bug bug = new Bug(getPriority(warning), StringUtils.defaultIfEmpty(
hashToMessageMapping.get(warning.getInstanceHash()), message), category, type,
sourceLine.getStartLine(), sourceLine.getEndLine());
bug.setInstanceHash(warning.getInstanceHash());
bug.setRank(warning.getBugRank());
boolean ignore = setCloudInformation(collection, warning, bug);
if (!ignore) {
bug.setNotAProblem(false);
bug.setFileName(findSourceFile(project, sourceFinder, sourceLine));
bug.setPackageName(warning.getPrimaryClass().getPackageName());
bug.setModuleName(actualName);
setAffectedLines(warning, bug);
annotations.add(bug);
bug.intern(stringPool);
}
}
return applyFilters(annotations);
}
3、修改message.xml,将忽略的类型描述信息改为<ShortDescription>ignore</ShortDescription>
4、重新build findbugs.jar
cd E:\find\findbugs-plugin-findbugs-4.72\findbugs-plugin-findbugs-4.72
#注:test类中会有一些校验,build时要跳过
maven -D maven.test.skip=true clean install
注:构建时如果因缺少依赖失败,可以将maven地址调整为http://repo.jenkins-ci.org/public/
5、将4中生成的jar放到jenkins findbugs插件目录中(/root/.jenkins/plugins/findbugs/WEB-INF/lib/),重新启动jenkins
总结
通过上述步骤调整,以后再调整检测规则只要修改message.xml,替换jar中的文件然后重启jenkins即可,被替换后的findbugs.jar是不影响jenkins检测的,不用再重新build源码。此外在分析代码过程中发现findbugs插件git上的描述为This plugin reached end-of-life,功能已经集成到warnings-ng-plugin中,目前jenkins中还不能搜索到此插件,只能搜索到warnings-plugin(warnings-ng-plugin的上一个版本,已经reached end-of-life),后续推出后可以体验一下。
附上修改后的findbugs插件:https://gitee.com/carpo/carpo/tree/master/tools/jenkins-findbugs-plugin