Docker+Jenkins持续集成环境(3)集成PMD、FindBugs、Checkstyle静态代码检查工具并邮件发送检查结果

为了规范代码,我们一般会集成静态代码检测工具,比如PMD、FindBugs、Checkstyle,那么Jenkins如何集成这些检查工具,并把检查结果放到构建邮件里呢?

今天做了调研和实现,过程如下

首先看,最终效果:

1.pom.xml

build。plugins 增加:

<plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                        <configuration>
                            <finalName>${project.artifactId}-${project.version}</finalName>
                            <appendAssemblyId>false</appendAssemblyId>
                            <descriptors>
                                <descriptor>src/assembly/assembly-descriptor.xml</descriptor>
                            </descriptors>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>findbugs-maven-plugin</artifactId>
                <version>3.0.5</version>
                <configuration>
                    <threshold>High</threshold>
                    <effort>Default</effort>
                    <findbugsXmlOutput>true</findbugsXmlOutput>
                    <findbugsXmlWithMessages>true</findbugsXmlWithMessages>
                    <xmlOutput>true</xmlOutput>
                    <formats><format>html</format></formats>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-pmd-plugin</artifactId>
                <version>3.8</version>
            </plugin>

reporting 增加:

    <reporting>
        <plugins>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-checkstyle-plugin</artifactId>
                <version>3.0.0</version>
                <reportSets>
                    <reportSet>
                        <reports>
                            <report>checkstyle</report>
                        </reports>
                    </reportSet>
                </reportSets>
            </plugin>

            <!--pmd-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-pmd-plugin</artifactId>
                <configuration>
                    <linkXref>true</linkXref>
                    <sourceEncoding>utf-8</sourceEncoding>
                    <minimumTokens>100</minimumTokens>
                    <targetJdk>1.8</targetJdk>
                    <excludes>
                        <exclude>**/*Bean.java</exclude>
                        <exclude>**/generated/*.java</exclude>
                    </excludes>
                    <excludeRoots>
                        <excludeRoot>target/generated-sources/stubs</excludeRoot>
                    </excludeRoots>
                </configuration>
                <version>3.8</version>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jxr-plugin</artifactId>
                <version>2.5</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-report-plugin</artifactId>
                <version>2.14.1</version>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>cobertura-maven-plugin</artifactId>
            </plugin>

        </plugins>
    </reporting>

2 jenkins设置

2.1 安装相关插件

直接搜索安装:

  • Checkstyle Plug-in
  • PMD Plug-in
  • FindBugs Plug-in
  • Static Analysis Collector Plug-in

邮件插件安装:

  • Email Extension Plugin
  • Email Extension Template Plugin

2.2 项目配置

maven构建Goals设置为:
pmd:pmd checkstyle:checkstyle findbugs:findbugs package -DskipTests

在构建设置里,勾上

  • Publish Checkstyle analysis results
  • Publish FindBugs analysis results
  • Publish PMD analysis results

构建后操作,添加Publish combined static analysis results,默认设置即可。

2.3 邮件配置

首先在系统设置里,配置Extended E-mail Notification部分

设置:

  • Default Subject : 自动构建通知:$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!
  • Default Content: ${JELLY_SCRIPT, template="analysis.jelly"}

剩下的自己配置下SMTP和收件人。

这里邮件内容使用analysis.jelly,使用jelly script,系统没有这个模板,我们需要配置一下:

打开系统管理-Managed files,增加一个Extended Email Publisher Jelly Template

模板文件如下,该模板修改自官方的模板,做了一定的本地化和样式调整:

<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define">
  <html>
    <head>
      <title>${project.name}</title>
      <style>
        body table, td, th, p, h1, h2 {
        margin:0;
        font:normal normal
        100% Georgia, Serif;
        }
        h1, h2 {
        border-bottom:dotted 1px #999999;
        padding:5px;
        margin-bottom:10px;
        color: #000000;
        font: normal bold 130%
        Georgia,Serif;
        background-color:#f0f0f0;
        }
        tr.gray {
        background-color:#f0f0f0;
        }
        h2 {
        padding:5px;
        margin-top:5px;
        margin-bottom:5px;
        font: italic bold 110% Georgia,Serif;
        }
        .bg2 {
        color:black;
        background-color:#E0E0E0;
        font-size:110%
        }
        th {
        font-weight: bold;
        }
        tr, td, th {
        padding:2px;
        }
        td.test_passed {
        color:blue;
        }
        td.test_failed {
        color:red;
        }
        td.center {
          text-align: center;
        }
        td.test_skipped {
        color:grey;
        }
        .console {
        font: normal normal 90% Courier New,
        monotype;
        padding:0px;
        margin:0px;
        }
        div.content, div.header {
        background: #ffffff;
        border: dotted
        1px #666;
        margin: 2px;
        content:
        2px;
        padding: 2px;
        }
        table.border, th.border, td.border {
        border:
        1px solid black;
        border-collapse:collapse;
        }
        .round_border{margin-bottom:5px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;margin-top:0;font-size:14px;padding:6px;border:1px solid #ccc}
.status{background-color:<j:choose><j:when test="${build.result=='SUCCESS'}">green</j:when><j:otherwise>red</j:otherwise></j:choose>;font-size:28px;font-weight:bold;color:white;height:52px;margin-bottom:18px;text-align:center;vertical-align:middle;border-collapse:collapse;background-repeat:no-repeat}
.status .info{color:white!important;text-shadow:0 -1px 0 rgba(0,0,0,0.3);font-size:32px;line-height:36px;padding:8px 0}
      </style>
    </head>
    <body>
      <div class="status">
          <p class="info">${project.name}构建<j:choose><j:when test="${build.result=='SUCCESS'}">成功</j:when><j:otherwise>失败</j:otherwise></j:choose></p>
      </div>
      <div class="header round_border">
        <j:set var="spc" value="  " />
        <h1>基本信息</h1>
        <table>
          <tr>
            <td>构建地址</td>
            <td>
              <a href="${rooturl}${build.url}">${rooturl}${build.url}</a>
            </td>
          </tr>
          <tr>
            <td>项目:</td>
            <td>${project.name}</td>
          </tr>
          <tr>
            <td>构建时间:</td>
            <td>${it.timestampString}</td>
          </tr>
          <tr>
            <td>构建耗时:</td>
            <td>${build.durationString}</td>
          </tr>
          <tr>
            <td>构建原因:</td>
            <td>
              <j:forEach var="cause" items="${build.causes}">${cause.shortDescription}
              </j:forEach>
            </td>
          </tr>
          <tr>
            <td>构建描述:</td>
            <td>${build.description}</td>
          </tr>
          <tr>
            <td>构建服务器:</td>
            <td>
              <j:choose>
                <j:when test="${build.builtOnStr!=''}">${build.builtOnStr}</j:when>
                <j:otherwise>master</j:otherwise>
              </j:choose>
            </td>
          </tr>
        </table>
      </div>

      <!-- HEALTH TEMPLATE -->
      <div class="content round_border">
        <j:set var="healthIconSize" value="16x16" />
        <j:set var="healthReports" value="${project.buildHealthReports}" />
        <j:if test="${healthReports!=null}">
          <h1>构建健康报告</h1>
          <table>
            <tr>
              <th>W</th>
              <th>Description</th>
              <th>Score</th>
            </tr>
            <j:forEach var="healthReport" items="${healthReports}">
              <tr>
                <td>
                  <img
                    src="${rooturl}${healthReport.getIconUrl(healthIconSize)}" />
                </td>
                <td>${healthReport.description}</td>
                <td>${healthReport.score}</td>
              </tr>
            </j:forEach>
          </table>
          <br />
        </j:if>
      </div>

      <!-- CHANGE SET -->
      <div class="content round_border">
        <j:set var="changeSet" value="${build.changeSet}" />
        <j:if test="${changeSet!=null}">
          <j:set var="hadChanges" value="false" />
          <a href="${rooturl}${build.url}/changes">
            <h1>代码变更记录</h1>
          </a>
          <j:forEach var="cs" items="${changeSet.logs}"
            varStatus="loop">
            <j:set var="hadChanges" value="true" />
            <h2>${cs.msgAnnotated}</h2>
            <p>
              by <em>${cs.author}</em>
            </p>
            <table>
              <j:forEach var="p" items="${cs.affectedFiles}">
                <tr>
                  <td width="10%">${spc}${p.editType.name}</td>
                  <td>
                    <tt>${p.path}</tt>
                  </td>
                </tr>
              </j:forEach>
            </table>
          </j:forEach>
          <j:if test="${!hadChanges}">
            <p>无变更</p>
          </j:if>
          <br />
        </j:if>
      </div>

      <!-- ARTIFACTS -->
      <j:set var="artifacts" value="${build.artifacts}" />
      <j:if test="${artifacts!=null and artifacts.size()&gt;0}">
        <div class="content round_border">
          <h1>构建产物</h1>
          <ul>
            <j:forEach var="f" items="${artifacts}">
              <li>
                <a href="${rooturl}${build.url}artifact/${f}">${f}</a>
              </li>
            </j:forEach>
          </ul>
        </div>
      </j:if>

      <!-- MAVEN ARTIFACTS -->
      <j:set var="mbuilds" value="${build.moduleBuilds}" />
      <j:if test="${mbuilds!=null}">
        <div class="content round_border">
          <h1>MAVEN 构建产物</h1>
          <j:forEach var="m" items="${mbuilds}">
            <h2>${m.key.displayName}</h2>
            <j:forEach var="mvnbld" items="${m.value}">
              <j:set var="artifacts" value="${mvnbld.artifacts}" />
              <j:if test="${artifacts!=null and artifacts.size()&gt;0}">
                <ul>
                  <j:forEach var="f" items="${artifacts}">
                    <li>
                      <a href="${rooturl}${mvnbld.url}artifact/${f}">${f}</a>
                    </li>
                  </j:forEach>
                </ul>
              </j:if>
            </j:forEach>
          </j:forEach>
          <br />
        </div>
      </j:if>

      <!-- JUnit TEMPLATE -->
      <j:set var="junitResultList" value="${it.JUnitTestResult}" />
      <j:if test="${junitResultList.isEmpty()!=true}">
        <div class="content round_border">
          <a href="${rooturl}${build.url}/testReport">
            <h1>JUnit Tests</h1>
          </a>
          <table class="border">
            <tr>
              <th class="border">Package</th>
              <th class="border">Failed</th>
              <th class="border">Passed</th>
              <th class="border">Skipped</th>
              <th class="border">Total</th>
            </tr>
            <j:forEach var="junitResult" items="${it.JUnitTestResult}">
              <j:forEach var="packageResult" items="${junitResult.getChildren()}">
                <tr>
                  <td class="border">
                    <tt>${packageResult.getName()}</tt>
                  </td>
                  <td class="border test_failed">${packageResult.getFailCount()}</td>
                  <td class="border test_passed">${packageResult.getPassCount()}</td>
                  <td class="border test_skipped">${packageResult.getSkipCount()}</td>
                  <td class="border">
                    <b>${packageResult.getPassCount()+packageResult.getFailCount()+packageResult.getSkipCount()}
                    </b>
                  </td>
                </tr>
                <j:forEach var="failed_test"
                  items="${packageResult.getFailedTests()}">
                  <tr>
                    <td class="test_failed" colspan="5">
                      <tt>${failed_test.getFullName()}</tt>
                    </td>
                  </tr>
                </j:forEach>
              </j:forEach>
            </j:forEach>
          </table>
          <br />
        </div>
      </j:if>

      <!-- Static Analysis -->
      <j:set var="actions" value="${it.staticAnalysisActions}" />
      <j:if test="${!actions.isEmpty()}">
        <div class="content round_border">
          <h1>代码静态检查结果</h1>
          <table>
            <tr>
              <th>名称</th>
              <th>检查结果</th>
              <th>总数</th>
              <th>High</th>
              <th>Normal</th>
              <th>Low</th>
            </tr>
            <j:forEach var="action" items="${actions}">
              <tr>
                <td>
                  <a href="${rooturl}${build.url}/${action.urlName}">${action.displayName}</a>
                </td>
                <td class="center">
                  <j:choose>
                    <j:when test="${action.result.pluginResult=='SUCCESS'}">
                      <img src="${rooturl}static/e59dfe28/images/16x16/blue.gif" />
                    </j:when>
                    <j:when test="${action.result.pluginResult=='FAILURE'}">
                      <img src="${rooturl}static/e59dfe28/images/16x16/red.gif" />
                    </j:when>
                    <j:otherwise>
                      <img src="${rooturl}static/e59dfe28/images/16x16/yellow.gif" />
                    </j:otherwise>
                  </j:choose>
                </td>
                <td class="center">${action.result.numberOfAnnotations} </td>
                <td class="center">${action.result.getNumberOfAnnotations('HIGH')} </td>
                <td class="center">${action.result.getNumberOfAnnotations('NORMAL')} </td>
                <td class="center">${action.result.getNumberOfAnnotations('LOW')} </td>
              </tr>
            </j:forEach>
          </table>
        </div>
      </j:if>

      <div class="content round_border">
        <!-- CONSOLE OUTPUT -->
        <a href="${rooturl}${build.url}/console">
          <h1>Console 输出结果(后50行)</h1>
        </a>
        <table class="console">
          <j:forEach var="line" items="${build.getLog(50)}">
            <tr>
              <td>
                <tt>${line}</tt>
              </td>
            </tr>
          </j:forEach>
        </table>
        <br />
      </div>
    </body>
  </html>
</j:jelly>

保存。

然后配置系统管理——Editable Email Notification Templates,增加一个默认模板,名称为默认,直接保存。

回到项目配置, 在构建环境里,
勾上Provide Configuration files
选择File为刚新增的jelly文件,target填写/var/jenkins_home/email-templates
Variable填写analysis.jelly

然后,在构建后操作里增加Editable Email Notification Templates,选择默认模板。

这样就完成了配置。


作者:Jadepeng
出处:jqpeng的技术记事本--http://www.cnblogs.com/xiaoqi
您的支持是对博主最大的鼓励,感谢您的认真阅读。
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

原文地址:https://www.cnblogs.com/xiaoqi/p/Jenkins-email-and-code-check.html

时间: 2024-10-22 02:41:48

Docker+Jenkins持续集成环境(3)集成PMD、FindBugs、Checkstyle静态代码检查工具并邮件发送检查结果的相关文章

Docker+Jenkins持续集成环境(2)使用docker+jenkins构建nodejs前端项目

前文使用Docker搭建Jenkins+Docker持续集成环境我们已经搭建了基于docker+jenkins的持续集成环境,并构建了基于maven的项目.这一节,我们继续扩展功能,增加对Nodejs的支持,实现nodejs项目构建.并打包成docker镜像和自动部署. 1. 配置Nodejs环境 1.1 安装nodejs插件 打开系统管理——管理插件——可选插件,搜索NodeJS,选择NodeJS Plugin安装 1.2 配置nodejs 版本 系统管理 —— 全局工具配置 —— NodeJ

代码静态分析工具--PMD,Findbugs,CheckStyle

最近学习Mybatis的官方文档,看到了[项目文档]一节有很多内容没有见过,做个笔记,理解一下. PMD 扫描Java源代码,查找潜在的问题,如: 可能的bugs,如空的try/catch/finally/switch声明 死亡的代码,没有使用的本地变量,参数和私有方法 不合标准的代码,如String/StringBuffer用法 过于复杂的表达式,如不必要的if表达式 重复的代码,拷贝.粘贴的代码 FindBugs 它用来查找Java代码中存在的bug.它使用静态分析方法标识出Java程序中上

Git+Docker+Jenkins持续集成

组成: Git 作为版本控制库 Docker 搭建测试环境 Jenkins 作为持续集成服务 Jenkins实现CI(Continuous Integration)到CD(Continuous Delivery)的转换工具. 期望: 1.解决从开发–测试–上线等一系列环境统一及依赖问题 2.可实现不停服务发布上线和灰度(需要实现LB) 3.可实现发布回滚 4.方便devops及运维操作 思路: 客户或产品有新需求变更或者测试人员提出bug时,会提交事件到开发人员,开发人员得到通知,会对开发分支做

netcore + docker + jenkins 持续集成日志

要实现的目标 : 提交代码到github的master分支后, 触发webhook, jenkins从github上重新拉取代码=>编译=>打包成docker镜像=>重新发布 机器: centos 7.4 1. 安装git,jenkins,docker-ce git可以直接yum 安装 : yum install git -y 也可以安装新版本 参考文章:  https://linuxize.com/post/how-to-install-git-on-centos-7/ jenkins

Linux下Jenkins+git+gradle 持续集成环境搭建

一.项目介绍 和 linux 环境搭建 本教程讲解 Linux下Jenkins+git+gradle 持续集成环境搭建,后续会加入 gerrit代码审核 和 robotium自动化测试 1.基本流程如下: androidstudio--  gerrit  --- git(github)   ----jenkins ---gradle ----  robotium  结果 使用AndroidStudio 开发,提交到gerrit进行代码审核,审核后提交给git(可以自己搭建git服务也可以使用gi

基于Jenkins持续集成CI

持续集成强调开发人员提交了新代码之后,立刻进行构建.(单元)测试.根据测试结果,我们可以确定新代码和原有代码能否正确地集成在一起. 持续交付在持续集成的基础上,将集成后的代码部署到更贴近真实运行环境的「类生产环境」(production-like environments)中.比如,我们完成单元测试后,可以把代码部署到连接数据库的 Staging 环境中更多的测试.如果代码没有问题,可以继续手动部署到生产环境中 持续部署则是在持续交付的基础上,把部署到生产环境的过程自动化. 集成:是指软件个人研

【持续集成】使用Jenkins实现多平台并行集成

使用Jenkins实现多平台并行集成 二月 15, 2012 暂无评论 我们的后端C应用都是支持跨平台的,至少目前在Linux和Solaris上运行是没有问题的,这样一来我们在配置持续集成环境时就要考虑如何实现在代码Commit后触发多平台并行(同时)集成这个需求. 之前使用Buildbot时是通过为一个Scheduler配置多个Builder满足这个需求的.但现在要换成Jenkins,我们如何来实现呢?昨天在折腾Jenkins时我把问题想简单了,今天细致查看了一下Build Log后才发现之前

php集成环境和自己配置的区别,php集成环境、php绿色集成环境、php独立安装版环境这三者的区别

最近有学生问我,直接使用PHP集成环境和我们自己独立安装的php环境有什么不一样吗? 答:PHP集成环境,和自己安装的php环境实际上没啥区别的,只不过大部分的集成环境进行了一些绿化操作,本质上没啥区别. 下面我们先来介绍一下集成环境的基本概念.常见的php集成环境以及集成环境的选择,然后再详细说明PHP集成环境与安装版的具体区别. 你们应该会经常听到WAMP这词吧,那么WAMP是什么意思? Windows下的Apache+Mysql+PHP,称为WAMP. 而Linux系统下的Apache+M

谈谈对Jenkins持续构建的认识

通过多次搭建Jenkins持续构建环境,终于对Jenkins有了进一步认识,在此把所学所得和大家分享一下,希望可以帮助大家快速掌握Jenkins的核心思想. 在安装完Jenkins的setup.exe程序后,在浏览器会自动打开Jenkins的主页,通过Jenkins主页配置各种参数.  过程一:安装Jenkins的MsBuild Plugin插件,此插件用于支持MSBuild.exe的构建工作: 过程二:配置插件,告诉MsBuild Plugin插件用哪个版本的MSBuild.exe来构建,比如