zoukankan      html  css  js  c++  java
  • 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
    您的支持是对博主最大的鼓励,感谢您的认真阅读。
    本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    我爱java系列之---【微服务间的认证—Feign拦截器】
    我爱java系列之---【设置权限的三种解决方案】
    581. Shortest Unsorted Continuous Subarray
    129. Sum Root to Leaf Numbers
    513. Find Bottom Left Tree Value
    515. Find Largest Value in Each Tree Row
    155. Min Stack max stack Maxpop O(1) 操作
    painting house
    Minimum Adjustment Cost
    k Sum
  • 原文地址:https://www.cnblogs.com/xiaoqi/p/Jenkins-email-and-code-check.html
Copyright © 2011-2022 走看看