1.Sonarqube Api介绍
sonarqube开放了很多api接口,用户及权限,项目及扫描结果,还有相关系统及配置等api。
api清单可以在sonar平台直接查看,默认地址为:http://localhost:9000/web_api/,localhost:9000是sonar的访问路径需要替换成你的地址,笔者的是绑定了域名的sonar.xxx.cn。
SonarqubeApi页面
2.获取扫描结果并与Jenkins集成控制发布质量
上文我们通过Jenkins实现了自动化扫描,但我们并没有对扫描结果进行获取或处理,这样导致整个扫描在整体发布流程中变成一个可有可无的弱势环节。
接下来我们将提升扫描环节的重要度,通过对其结果获取控制发布流程,思路发下:
1.通过api获取我们所需要采集的扫描指标值(每公司或团队关注的指标会有略有差异)
2.对指标质量规则建模,实现控制方案的数据模型
3.包装成一个可直接使用的接口供jenkins集成
4.jenkins通过调用我们包装好的接口获取扫描结果,并根据结果控制流程
步骤1:API获取指标
通过对API分析,我们找到如下获取指标的API
http://sonar.xxxx.cn/api/measures/search?projectKeys=项目 key&metricKeys=code_smells,bugs,coverage,duplicated_lines_density,ncloc,security_rating,vulnerabilities,comment_lines_density
调用后返回结果如下:
{ "measures": [{ "metric": "bugs", "value": "0", "component": "netCore01", "bestValue": true }, { "metric": "code_smells", "value": "3", "component": "netCore01", "bestValue": false }, { "metric": "comment_lines_density", "value": "2.8", "component": "netCore01", "bestValue": false }, { "metric": "coverage", "value": "0.0", "component": "netCore01", "bestValue": false }, { "metric": "duplicated_lines_density", "value": "0.0", "component": "netCore01", "bestValue": true }, { "metric": "ncloc", "value": "138", "component": "netCore01" }, { "metric": "security_rating", "value": "1.0", "component": "netCore01", "bestValue": true }, { "metric": "vulnerabilities", "value": "0", "component": "netCore01", "bestValue": true }]}说明:具体指标获取可以在项目--指标然后左侧各种指标点击查看,URL中会有该指标的字段名
步骤2:质量规则建模
以上接口我们获取了一些主要的扫描结果,但这些指标数据如何控制更合理,是每个团队需要考虑的事情,本例为演示技术实现为主,建模不具实际业务参考。
强制规则:首先我们认为BUG及安全漏洞是系统不能允许出现的,一旦有这两项,则需要先修复才能部署
扣分规则:不同的问题类型我们扣分权重不同,通过加权*数量进行扣分计算
通过阈值:如果强制规则通过,则验证最低通过分阈值判断是否通过
策略是否通过扣分对应字段
漏洞大于0否漏洞数*5vulnerabilities 安全漏洞数量
BUG大于0否BUG数*5bugs BUG数量
code_smells数量扣分code_smells*2code_smells 代码坏味道数量
duplicated_lines_density扣分duplicated_lines_density>5%则单独扣分规则duplicated_lines_density重复行比例
comment_lines_density扣分comment_lines_density<7%则单独扣分规则comment_lines_density代码注释比例
还有其他几个指标,不再逐一讲解。
步骤3:对数据模型及sonar Api包装成专用api
服务接口采用.netCore开发,主要是vs开发工具的确太好用,然后用k8s部署即可
主要代码逻辑如下:
API层:
[Route("[controller]/[action]")][ApiController]publicclassSonarController:Controller{staticstringfields="code_smells,bugs,coverage,duplicated_lines_density,ncloc,security_rating,vulnerabilities,comment_lines_density";staticstringsonarRootUrl="http://sonarqube.default:9000";staticfloatminScore=70f;//分数通过阈值publicSonarResultScan(stringprojectKey){stringurl=string.Format(sonarRootUrl+"/api/measures/search?projectKeys="+projectKey+"&metricKeys="+fields);stringresult=HttpHelper.HttpGet(url,"application/json");SonarScanResultscanResult=result.FromJSON<SonarScanResult>();returnnewSonarResult(scanResult,minScore);}}
数据处理部分
publicclassSonarScanResult{publicList<SonarScanResultItem>measures{get;set;}}publicclassSonarScanResultItem{publicstringmetric{get;set;}publicstringvalue{get;set;}publicstringcomponent{get;set;}publicboolbestValue{get;set;}}publicclassSonarResult{publicList<SonarScanResultItem>measures;/// <summary>/// 坏味道/// </summary>publicfloatcode_smells{get;set;}/// <summary>/// BUG/// </summary>publicfloatbugs{get;set;}/// <summary>/// 覆盖率/// </summary>publicfloatcoverage{get;set;}/// <summary>/// 重复率/// </summary>publicfloatduplicated_lines_density{get;set;}/// <summary>/// 代码行数/// </summary>publicfloatncloc{get;set;}//代码行数/// <summary>/// /// </summary>publicfloatsecurity_rating{get;set;}/// <summary>/// 漏洞数量/// </summary>publicfloatvulnerabilities{get;set;}/// <summary>/// 可靠性/// </summary>publicfloatreliability_rating{get;set;}/// <summary>/// 注释占比/// </summary>publicfloat?comment_lines_density{get;set;}/// <summary>/// 总体得分/// </summary>publicfloatScore{get;set;}/// <summary>/// 是否通过/// </summary>publicboolPass{get;set;}publicstringMsg{get;set;}privatefloatminScore;publicSonarResult(SonarScanResultresult,floatminScore){this.minScore=minScore;if(result!=null&&result.measures!=null){this.measures=result.measures;}else{this.measures=newList<SonarScanResultItem>();}this.OutputResult();}/// <summary>/// 计算输出结果/// </summary>publicvoidOutputResult(){this.code_smells=GetMetricValue("code_smells");this.bugs=GetMetricValue("bugs");this.coverage=GetMetricValue("coverage");this.duplicated_lines_density=GetMetricValue("duplicated_lines_density");this.ncloc=GetMetricValue("ncloc");this.security_rating=GetMetricValue("security_rating");this.vulnerabilities=GetMetricValue("vulnerabilities");this.reliability_rating=GetMetricValue("reliability_rating");comment_lines_density=GetMetricValue2("comment_lines_density");this.Pass=true;if(bugs>0||vulnerabilities>0){//强制不通过,分数0,别怪我为难程序员,我也是被刁难了多年this.Pass=false;this.Score=0;this.Msg=string.Format("漏洞:{0},BUG:{1},不满足发布策略",vulnerabilities,bugs);}else{doublecutScore=bugs*5+code_smells*2+security_rating*2.5+vulnerabilities*5;if(comment_lines_density.HasValue&&comment_lines_density<7)//7.0%的注释为一个及格线,大于7%不扣分{cutScore+=(7-comment_lines_density.Value);}if(duplicated_lines_density>5){cutScore+=(comment_lines_density.Value-5);//重复率每增加1百分比,扣1分}this.Score=100-(float)cutScore;this.Pass=this.Score>=minScore;if(!this.Pass)this.Msg="该代码综合质量评分过低,需改进后方可准入部署环境";elsethis.Msg="代码综合质量分为:"+this.Score+",允许部署";}}privatefloatGetMetricValue(stringkey){varitem=this.measures.FirstOrDefault(p=>p.metric==key);if(item==null)return0f;returnConvertHelper.Tofloat(item.value,0f);}privatefloat?GetMetricValue2(stringkey){varitem=this.measures.FirstOrDefault(p=>p.metric==key);if(item==null)returndefault(float?);returnConvertHelper.Tofloat2(item.value);}}
部署接口到k8s,然后验证接口返回
{"code_smells":3,"bugs":0,"coverage":0,"duplicated_lines_density":0,"ncloc":138,"security_rating":1,"vulnerabilities":0,"reliability_rating":0,"comment_lines_density":2.8,"score":87.3,"pass":true,"msg":"代码综合质量分为:87.3,允许部署"}
步骤4:Jenkins集成质量检查Api控制发布流程
在昨天我们Jenkins执行扫描完毕环节后添加发下脚本:
//说明:sonarCheckUrl是我们上面用.net core实现的API,地址:http://xxxxx/checkApi/Sonar/Scan?projectKey=$sonarKey def response = httpRequest acceptType: 'APPLICATION_JSON', contentType: 'APPLICATION_JSON', httpMode: 'GET', url: "$sonarCheckUrl?projectKey=$sonarKey" def responseBodyJson = readJSON text: response.content if (responseBodyJson.pass) { println("#############################################代码质量检测通过,综合得分:"+responseBodyJson.score+ "##################################################") } else { println("#############################################代码质量检测不通过,综合得分:"+responseBodyJson.score+"原因" + responseBodyJson.msg+ ",流水线退出##################################################") sh "exit 1" }
修改完毕后,我们重新执行发布过程,发布结果输出如下:
这里是刚扫描结束INFO:Totaltime:5.882sINFO:FinalMemory:12M/44MINFO:------------------------------------------------------------------------TheSonarQubeScannerhas finished12:40:54.591Post-processing succeeded.[Pipeline]echo #############################################代码质量检查完毕##################################################[Pipeline]echo #############################################开始请求质量检查结果##################################################[Pipeline]httpRequest HttpMethod:GETURL:[http://api.xxxx.cn/checkApi//onar/Scan?projectKey=netCore01](http://api.xxxx.cn/checkApi//Sonar/Scan?projectKey=netCore01)Content-Type:application/jsonAccept:application/jsonSendingrequest to url:[http://api.xxxx.cn/checkApi/Sonar/Scan?projectKey=netCore01](http://api.xxx.cn/checkApi/Sonar/Scan?projectKey=netCore01)ResponseCode:HTTP/1.1200OKSuccesscodefrom[100‥399][Pipeline]echo sonar Response:Status:200[Pipeline]echo response.content:{"code_smells":3,"bugs":0,"coverage":0,"duplicated_lines_density":0,"ncloc":138,"security_rating":1,"vulnerabilities":0,"reliability_rating":0,"comment_lines_density":2.8,"score":87.3,"pass":true,"msg":"代码综合质量分为:87.3,允许部署"}[Pipeline]readJSON[Pipeline]echo#############################################代码质量检测通过,综合得分:87.3################################################## [Pipeline]}[Pipeline]// withEnv
3. 小结
本文通过对Sonar Api扩展及集成,实现了自定义的代码质量控制模型及策略,这种方案相对更灵活一些。
您也可以使用sonarqube中自带的【质量阈】,通过界面配置不同的策略进行控制的方式。
另外API获取数据的方案您也可以改为从sonar数据库中查询数据的方式获取,但该方式容易因为版本升级出现不兼容问题。
3.1 Sonar质量阈方案
Sonarqube质量阈控制
3.2 SQL查询数据方案
先查出项目uuid:
SELECT project_uuid,kee FROM projects where kee='projName'
--BUG
SELECT * FROM issues WHERE project_uuid='项目UUID' and issue_type=2
--漏洞
SELECT * FROM issues WHERE project_uuid='项目UUID' and issue_type=3
--坏味道
SELECT * FROM issues WHERE project_uuid='项目UUID' and issue_type=1
若要分级别获取,可以再加上条件
severity =
['BLOCKER','CRITICAL',"MAJOR",'MINOR','INFO']
对应含义:阻断/严重/主要/次要/提示
作者:上岸的魚
链接:https://www.jianshu.com/p/a0d77b0b4809
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
网友评论