Jenkins集成findbugs完成静态代码检查

背景

项目组出过几次NPE事故,为保障代码健壮性, 提高项目稳定性, 在项目中引入findbugs插件, 进行静态代码检查.

任务目标

  • Jenkins CI过程中, 引入静态代码检查, 生成检查报告
  • 引入bug模板, 实现检查内容可配置
  • 代码检查发现bug时, 阻断maven构建流程, 发送邮件告警

实施过程

引入maven插件findbugs-maven-plugin

注意点:

  • 与pipeline配合, 在install阶段再报错, 让pipeline在compile阶段生成报告
  • 配置includeFilterFile, 自定义bug检查类型
  • 一些反向工程的代码可以配置节点, 不做bug检查
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>findbugs-maven-plugin</artifactId>
    <version>3.0.5</version>
    <configuration>
    <failOnError>true</failOnError>
    <findbugsXmlOutput>true</findbugsXmlOutput>
    <xmlOutput>true</xmlOutput>
    <includeFilterFile>${basedir}/src/main/resources/findbugs-include.xml</includeFilterFile>
    </configuration>
    <executions>
    <execution>
    <id>failOnError</id>
    <phase>install</phase>
    <goals>
    <goal>check</goal>
    </goals>
    <configuration>
    <effort>Max</effort>
    <threshold>High</threshold>
    <failOnError>true</failOnError>
    </configuration>
    </execution>
    </executions>
    </plugin>

注意点:

配置不需要检查的模块

1
2
3
4
5
6
7
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>

自定义bug检查类型. findbugs-include.xml

注意:

  • 当前阶段, 只配置了NP RCN两个, 大家可以根据需要配置对应目录/类和检查类型. (bug code/pattern 参考)
  • 相应的, 如果有不想检查的目录/类, 可以配置findbugs-exclude.xml, 道理与findbugs-include.xml相同
    1
    2
    3
    4
    5
    6
    7
    <?xml version="1.0" encoding="UTF-8"?>
    <FindBugsFilter>
    <Match>
    <Package name="~com\.xxxxx\.xxxx\.xxxx\.author.*"/>
    <Bug code="NP,RCN"/>
    </Match>
    </FindBugsFilter>

jenkins pipeline

重点内容:

  • 新增stage Verify, 在compile后执行findbugs, 在此stage中生成报告
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    pipeline {
    agent {
    node {
    label 'maven-jdk1.8'
    }
    }
    stages {
    stage('Verify'){
    steps {
    sh 'mvn -B -U clean compile findbugs:findbugs'
    findbugs(pattern: '**/target/findbugsXml.xml')
    }
    }
    stage('Build') {
    steps {
    sh 'mvn -B -U clean install'
    }
    }
    }
    post {
    failure {
    script {
    def changeStr = getChangeString()
    emailext body:
    """Job '${env.JOB_NAME}:${env.BUILD_NUMBER}\' 失败!\n
    commit记录:
    ${changeStr}
    点击进入Jenkins查看详情: ${env.BUILD_URL}""",
    compressLog: true,
    attachLog: true,
    subject:"构建失败: ${env.JOB_NAME}:${env.BUILD_NUMBER}",
    to:"alarmemail@xxxx.com"
    }
    }
    }
    triggers {
    cron('H H/2 * * *')
    gitlab(triggerOnPush: true, triggerOnMergeRequest: true, branchFilterType: 'All')
    }
    }

    def getChangeString() {
    def changeString = ""
    def changeLogSets = currentBuild.changeSets
    for (int i = 0; i < changeLogSets.size(); i++) {
    def entries = changeLogSets[i].items
    for (int j = 0; j < entries.length; j++) {
    def entry = entries[j]
    changeString += "-- "+"${entry.commitId} by ${entry.author} on ${new Date(entry.timestamp).format('yyyy-MM-dd HH:mm:ss')} ${entry.msg}"+"\n"
    }
    }
    if (!changeString) {
    changeString = "-- 无"
    }
    return changeString
    }

成果展示

参考文档:
http://findbugs.sourceforge.net/manual/index.html
https://stackoverflow.com/questions/38632682/maven-execute-a-goal-on-build-fail-findbugs