使用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-
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">新覆盖率<%;
<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就是上面步骤生成的

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

使用jenkins+sonar进行代码扫描,并发送自定义邮件的更多相关文章
- 持续集成工具之jenkins+sonarqube做代码扫描
上一篇我们主要聊了下代码质量管理平台sonarqube的安装部署以及它的工作方式做了简单的描述和代码扫描演示:回顾请参考https://www.cnblogs.com/qiuhom-1874/p/13 ...
- DEVOPS技术实践_05:sonar静态代码扫描
一.SonarQube静态代码扫描平台 1.1 安装 https://www.sonarqube.org/官网 1.2 下载软件包 https://www.sonarqube.org/download ...
- 03 . Jenkins构建之代码扫描
Sonar简介 Sonar 是一个用于代码质量管理的开放平台.通过插件机制,Sonar可以集成不同的测试工具,代码分析工具,以及持续集成工具.与持续集成工具(例如 Hudson/Jenkins 等)不 ...
- Sonar静态代码扫描环境搭建(Windows10)
一.环境配置: 1.jdk安装及配置 2.MySQL数据库安装----直接调用服务器院端的MySQL数据库,在此基础上创建新的数据库sonar. 数据库的配置如下: 3.sonar官网下载sonar ...
- jenkins集成robot用例并发送自定义报告
slave
- jenkins+sonar发送结果邮件的状态问题修复
在我的这篇博文中:使用jenkins+sonar进行代码扫描,并发送自定义邮件 邮件的配置为默认的$PROJECT_DEFAULT_SUBJECT 所以发送的邮件标题中的状态是jenkins构建的状态 ...
- 代码扫描利器sonarqube
sonar的作用 1.代码质量和安全扫描和分析平台. 2.多维度分析代码:代码量.安全隐患.编写规范隐患.重复度.复杂度.代码增量.测试覆盖率等. 3.支持25+编程语言的代码扫描口分析,包含java ...
- jenkins:集成sonar代码扫描+发送邮件
前提: Jenkins JDK 目录: 1.安装sonar插件:SonarQube Scanner for Jenkins 2.安装SonarQube 3.安装sonar-scanner ++++++ ...
- Jenkins集成openshift容器中进行代码扫描
1.Dockerfile sonarDockerfile: (基础slave镜像参考上篇博文) FROM registry.it.com/openshift/jenkins-slave:latest ...
随机推荐
- JAVA系列:浅谈Java中的equals和==
在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str2 = new String(&qu ...
- django Error: HINT: Add or change a related_name argument to the definition for 'UserProfile.groups' or 'User.groups'.
# 解决方案: 因自己重新封装user为UserProfile故在 settings中 添加自己的
- Django REST framework+Vue 打造生鲜电商项目(笔记六)
(部分代码来自https://www.cnblogs.com/derek1184405959/p/8836205.html) 九.个人中心功能开发 1.drf的api文档自动生成 (1) url #d ...
- QQ龙虎榜数据接口
1.个股全部上榜日期 strUrl.Format(L"http://stock.finance.qq.com/cgi-bin/sstock/q_lhb_js?t=1&c=%06d&q ...
- 2018 Arab Collegiate Programming Contest (ACPC 2018) G. Greatest Chicken Dish (线段树+GCD)
题目链接:https://codeforces.com/gym/101991/problem/G 题意:给出 n 个数,q 次询问区间[ li,ri ]之间有多少个 GCD = di 的连续子区间. ...
- python - Flask 基础(1)
这两天稍微接触了一点 Flask 框架,所以分享点基础 1. 配置文件 from flask import Flask app = Flask(__name__) # 使用自定义的配置文件 app.c ...
- dumpe/dumpe2fs/e2fsck
xt2/3/4文件系统备份工具 导出ext2/ext3/ext4文件系统信息 dumpe2fs e2fsck 强制检查文件系统 检查文件系统
- Count on a tree 树上主席树
Count on a tree 树上主席树 给\(n\)个树,每个点有点权,每次询问\(u,v\)路径上第\(k\)小点权,强制在线 求解区间静态第\(k\)小即用主席树. 树上主席树类似于区间上主席 ...
- svg创建分支
是这样的 我之前的项目上传到svn上一直没有开过分支,今天其中的一个项目改动会比较大,想创建一个分支,在此分支上修改(目的是改动如果比较大,不想影响原来主干上的分支) 首先打开我们的项目存放的文件:右 ...
- 爬虫之获取猫眼电影10W评论
第一步 打开一个电影的评论界面: 哪吒之魔童降世:https://maoyan.com/films/1211270 我们发现这里只显示10条评论,而我们需要爬取10w条数据,所以不能从此页面进行抓包, ...