使用jenkins+sonar进行代码扫描,并发送自定义邮件

jenkins架构

1、一台机器作为jenkins master不进行构建操作,只负责调度其他slave节点执行任务

2、一台slave机器作为执行机器存放从gitlab上拉取的代码,使用sonar-scanner进行代码扫描和使用sonarqube进行页面展示

步骤

1、在执行机上安装sonarqube和sonar-scanner两个工具

  执行机器主要任务有

  1、存储代码

  2、进行代码扫描

  3、根据自己编写的python脚本生成自定义的邮件内容

  4、sonar页面展示

下载地址:。。。。。。。

sonarqube安装及配置mysql数据库:http://www.pianshen.com/article/6431255831/

sonar-scanner安装:http://www.pianshen.com/article/1870255571/

2、jenkins master机器配置

  2.1 安装插件:SonarQube Scanner for Jenkins

  

 

  2.2 系统管理》系统设置配置sonarqube

    server authentication token中输入sonarqube中生成的token值。

    新版本jenkins可能需要先建凭据,再选择而不是直接输入token值,注意凭据的类型为Secret text

    

 

 

   2.3 系统管理》全局工具配置sonarqube scanner

 

3、配置节点(将slave机器注册到master上,以供后续master调用)

  3.1 增加节点

  

 

   3.2 节点配置

  

  3.4 节点启动

  

4、创建job

  4.1 创建自由风格的任务

   Restrict where this project can be run(指定此项目在哪个机器上运行),指向我们新建的slave节点机器

  

  拉取代码:

  构建步骤新增代码扫描配置

  前提:由于要执行sonar.py脚本,所以jenkins所在机器要有python3环境,且安装了pymysql、jinja2,

  进入到sonar.py所在目录,执行命令:call E:\Python36\python.exe E:\sonar\sonar_script\sonar.py 项目名

 

sonar.projectKey=A-yto-steward
sonar.projectName=A网-客户管家
sonar.projectVersion=1.0
sonar.sources=./
sonar.language=java
sonar.sourceEncoding=UTF-8
sonar.java.binaries=./
sonar.login=admin
sonar.password=admin

 

cd ../..
cd sonar_script
call E:\Python36\python.exe E:\sonar\sonar_script\sonar.py A网-客户管家

在执行机如下目录放sonar.py和table.html文件

sonar.py脚本内容

#!/usr/bin/python
# -*- coding:utf-8 -*-
# @Time   : 2018/11/20 13:16
# @Author : wnaglihua
# @File   : sonar.py

import pymysql,os,sys
from jinja2 import FileSystemLoader,Environment

def select_project_uuid(project_name):
    db = pymysql.connect(host="192.168.207.160", port=3306, user="sonar", passwd="sonar", db="sonar")
    cursor = db.cursor()
    select_p_uuid="SELECT project_uuid,kee FROM projects WHERE `name`= '%s'" %(project_name)
    cursor.execute(select_p_uuid)
    result = cursor.fetchone()
    p_uuid = result[0]
    projectKey = result[1]
    db.close()
    return(p_uuid, projectKey)

def select_total_info(p_uuid):
    total_info=[]
    # 使用cursor()方法获取操作游标
    db = pymysql.connect(host="192.168.207.160", port=3306, user="sonar", passwd="sonar", db="sonar")
    cursor = db.cursor()

    select_p_links = "SELECT text_value FROM project_measures WHERE text_value LIKE 'java=%' and component_uuid=" + "\'" + p_uuid + "\'"
    cursor.execute(select_p_links)
    p_links = cursor.fetchone()[0].split("=")[1]

    sql_info = "SELECT count(*) FROM issues WHERE project_uuid='%s' and issue_type =%s"
    for leak in [2,3,1]:
        search_data = sql_info %(p_uuid, leak)
        cursor.execute(search_data)
        total_info.append(cursor.fetchone()[0])
    db.close()
    return p_links,total_info

def select_bugs(p_uuid):
    bugs=[]
    db = pymysql.connect(host="192.168.207.160", port=3306, user="sonar", passwd="sonar", db="sonar")
    cursor = db.cursor()

    sql_info = "SELECT count(*) FROM issues WHERE project_uuid='%s' and issue_type =2 AND severity ='%s'"
    for leak in ['BLOCKER','CRITICAL',"MAJOR",'MINOR','INFO']:
        search_data=sql_info  % (p_uuid,leak)
        cursor.execute(search_data)
        bugs.append(cursor.fetchone()[0])
    db.close()
    return bugs

def select_leaks(p_uuid):
    leaks=[]
    db = pymysql.connect(host="192.168.207.160", port=3306, user="sonar", passwd="sonar", db="sonar")
    cursor = db.cursor()

    sql_info = "SELECT count(*) FROM issues WHERE project_uuid='%s' and issue_type =3 AND severity ='%s'"
    for leak in ['BLOCKER','CRITICAL',"MAJOR",'MINOR','INFO']:
        search_data=sql_info  % (p_uuid,leak)
        cursor.execute(search_data)
        leaks.append(cursor.fetchone()[0])
    db.close()
    return leaks

def select_bad_tastes(p_uuid):
    tastes=[]
    db = pymysql.connect(host="192.168.207.160", port=3306, user="sonar", passwd="sonar", db="sonar")
    cursor = db.cursor()

    sql_info="SELECT count(*) FROM issues WHERE project_uuid='%s' and issue_type =1 AND severity ='%s'"
    for leak in ['BLOCKER','CRITICAL',"MAJOR",'MINOR','INFO']:
        search_data=sql_info  % (p_uuid,leak)
        cursor.execute(search_data)
        tastes.append(cursor.fetchone()[0])
    return tastes
    db.close()

curpath = os.getcwd()
table_tem_name="table.html"    
def generate_errmsg_table(s_lines="", total_data=[], bugs=[],leaks=[],tastes=[],report_url=""):
    env = Environment(loader=FileSystemLoader(curpath, 'utf-8'))  # 创建一个包加载器对象
    template = env.get_template(table_tem_name)
    html_content = (template.render(lins=s_lines,total_data=total_data, bugs=bugs,leaks = leaks,tastes=tastes,report_url=report_url))
    fh = open(report_html_path, 'w')
    fh.write(html_content)
    fh.close()

project_name = sys.argv[1]
report_html_path="report\\"+project_name+".html"
p_uuid, projectKey=select_project_uuid(project_name)
s_lines,total_data=select_total_info(p_uuid)
bugs=select_bugs(p_uuid)
leaks=select_leaks(p_uuid)
tastes=select_bad_tastes(p_uuid)
report_url="http://192.168.207.140:9000/dashboard?id=%s" %(projectKey)
generate_errmsg_table(s_lines,total_data,bugs,leaks,tastes,report_url)

table.html脚本内容

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="GBK">
<body>
<p style="font-weight:bold;">一、总体情况:</p>
<ul>
<li style="font-weight:bold;">整体运行情况:扫描代码行数:<span style="color:blue">{{lins}}</span>, bugs:<span style="color:red">{{total_data[0]}}</span>, 漏洞:<span style="color:red">{{total_data[1]}}</span>, 坏味道:<span style="color:red">{{total_data[2]}}</span></li>
<li style="font-weight:bold;">URL地址:<a style="font-weight:bold;" href={{report_url}} >{{report_url}}</a></li>
</ul>
<p style="font-weight:bold;">二、错误信息详情:</p>
<table border="1" cellpadding="10" width="540" height="120">
    <tr ><th></th><th>阻断</th><th>严重</th><th>主要</th><th>次要</th><th>提示</th><th>总数</th></tr>
    <tr bgcolor=#ECFFFF><td>bugs</td><td align="center">{{bugs[0]}}</td><td align="center">{{bugs[1]}}</td><td align="center">{{bugs[2]}}</td><td align="center">{{bugs[3]}}</td><td align="center">{{bugs[4]}}</td><td align="center" style="color:red">{{total_data[0]}}</td></tr>
    <tr bgcolor=#D2E9FF><td>漏洞</td><td align="center">{{leaks[0]}}</td><td align="center">{{leaks[1]}}</td><td align="center">{{leaks[2]}}</td><td align="center">{{leaks[3]}}</td><td align="center">{{leaks[4]}}</td><td align="center" style="color:red">{{total_data[1]}}</td></tr>
    <tr bgcolor=#ECFFFF><td>坏味道</td><td align="center">{{tastes[0]}}</td><td align="center">{{tastes[1]}}</td><td align="center">{{tastes[2]}}</td><td align="center">{{tastes[3]}}</td><td align="center">{{tastes[4]}}</td><td align="center" style="color:red">{{total_data[2]}}</td></tr>
</table>
<br><span style="font-weight:bold;"><b style="color:red">代码扫描度量通过准则:</b></span>
<br><span style="font-size:14px">新覆盖率<80%;
<br><span style="font-size:14px">新代码中的重复行密度 (%)>30%;
<br><span style="font-size:14px">新代码可维护率劣于A;
<br><span style="font-size:14px">新代码可靠率劣于A;
<br><span style="font-size:14px">新代码安全率劣于A;
<br></br>
</body>
</html>

  邮件配置

  安装插件:Email Extension

  在系统管理》》系统设置中设置

 

 

 

job中国配置发送邮件

内容选择HTML,打开高级选项

增加触发器,并打开高级选项

输入发送邮箱列表,以英文逗号分隔,和邮件内容,html就是上面步骤生成的

  

   构建完成后会收到如下格式邮件

  

 

posted @ 2019-05-23 17:30  秋寻草  阅读(962)  评论(0编辑  收藏