基本思路:

每一行代码都有作者, 错误的代码更应该有作者。

本文的思路是, 通过火线静态代码扫描程序扫描后的 json 报告, 直接定位到人,也就是错误代码的引入者。

责任到人,可以更好地做到错误代码发现及时, 修复更及时。

准备条件:

火线静态代码扫描程序

1). 下载火线 jar 包 http://magic.360.cn/index.html

2). 编写配置文件 RedLineConfigurationNoLog.xml http://magic.360.cn/user.html#args

代码扫描服务器 - Linux CentOS 6 or 7

1). 安装 JDK

2). 准备预扫描项目的 git 目录,例如:/data/git/test

3). 发布 WEB 服务的文件夹, 用于发布火线报告 HTML 版, 例如: /data/webtest/fireline

3). jq 用于解析火线 json 报告的内容,

CentOS 7:yum install -y jq,

CentOS 6:需要自行下载安装,https://stedolan.github.io/jq/

脚本执行步骤:

一、火线静态代码扫描

git pull 更新扫描服务器上的代码

执行火线静态代码扫描命令

发布火线扫描报告 html

二、定位错误代码作者

检查火线扫描报告 json 文件内 block 和 error 条目的数量

根据错误代码的文件名和出错行数查找错误代码作者

脚本内容(/data/fireline/fireline.sh):

#! /bin/sh

# Author : binwei.liu

# Usage: 2017-09-02 火线静态代码扫描以及定位错误代码作者

#########################################

# 一、火线静态代码扫描

#########################################

# 1. git pull 更新扫描服务器上的代码

# 2. 执行火线静态代码扫描命令

# 3. 发布火线扫描报告html

#########################################

# 二、定位错误代码作者

#########################################

# 4. 检查火线扫描报告json文件内block和error条目的数量

# 5. 根据错误代码的文件名和出错行数查找错误代码作者

#########################################

PS4='+[$LINENO]'

RUN_TIME=$( date +'%Y%m%dT%H%M%S' )

# 设置扫描项目名称

# FIRELINE_PROJ_NAME=${1}

FIRELINE_PROJ_NAME='test'

# 设置已经准备好的项目git目录

# FIRELINE_SCAN_SRC_DIR=${2}

FIRELINE_SCAN_SRC_DIR='/data/git/test'

# 火线报告临时存放文件夹

FIRELINE_REPORT_SAVE_DIR="/tmp/report_${FIRELINE_PROJ_NAME}_${RUN_TIME}"

# 火线报告文件名

FIRELINE_REPORT_FILE_NAME="index_${FIRELINE_PROJ_NAME}"

# 火线报告提交人名称

FIRELINE_USER='binwei.liu'

# 火线程序jar包

FIRELINE_JAR='/data/fireline/fireline.jar'

# 火线程序配置文件路径

FIRELINE_CONFIG='/data/fireline/RedLineConfigurationNoLog.xml'

# 扫描服务器上,web服务发布的文件夹

PUBLIC_REPORT_DIR='/data/webtest/fireline'

# 火线报告内的json文件

FIRELINE_REPORT_JSON_FILE="/data/webtest/fireline/${FIRELINE_REPORT_FILE_NAME}.json"

# web报告发布后的查看地址

PUBLIC_REPORT_URL="http://www.17test.net/fireline/${FIRELINE_REPORT_FILE_NAME}.html"

# json报告里包含block条目的数量

JSON_BLOCK_ITEM_COUNT=0

# json报告里包含error条目的数量

JSON_ERROR_ITEM_COUNT=0

# 日志屏幕显示或者记录到指定文件

function log () {

# echo -e `date +'%Y-%m-%d %H:%M:%S'` "${*}" | tee -a ${LOG_FILE}

# echo -e "${*}" | tee -a ${LOG_FILE}

echo -e "${*}"

}

function init () {

log "##################################################"

log "报告链接: ${PUBLIC_REPORT_URL}"

log "规则文档: http://magic.360.cn/document.html"

log "##################################################"

# 建立报告临时存放文件夹

log "info: create new tmp report folder ${FIRELINE_REPORT_SAVE_DIR}"

mkdir -p ${FIRELINE_REPORT_SAVE_DIR}

}

function finalize () {

log "${2}"

exit ${1}

}

function update_local_code () {

log "info: update the local code to the latest."

cd ${FIRELINE_SCAN_SRC_DIR}

git reset --hard origin/master && \

git gc && \

git pull && \

git submodule init && \

git submodule update && \

git submodule foreach git checkout master && \

git submodule foreach git pull

if [[ $? -ne 0 ]]; then

finalize 1 "error: update the local code failed."

fi

}

function fireline_scan () {

log "info: fireline starts to scan the project of <${FIRELINE_PROJ_NAME}>"

java -jar ${FIRELINE_JAR} \

-Df ile.encoding=UTF-8 \

scanSrcDir=${FIRELINE_SCAN_SRC_DIR} \

reportSaveDir=${FIRELINE_REPORT_SAVE_DIR} \

reportFileName=${FIRELINE_REPORT_FILE_NAME} \

proj_name=${FIRELINE_PROJ_NAME} \

user=${FIRELINE_USER} \

config=${FIRELINE_CONFIG} > /dev/null 2&>1

if [[ $? -ne 0 ]]; then

finalize 1 "error: fireline scans project <${FIRELINE_PROJ_NAME}> failed."

else

log "info: fireline scans completely."

fi

}

function public_report_html () {

log "info: public the fireline report."

cp -rf ${FIRELINE_REPORT_SAVE_DIR}/* ${PUBLIC_REPORT_DIR}/

if [[ $? -ne 0 ]]; then

log "error: public the fireline report failed."

fi

}

function find_author_of_error_code () {

local _beginline=${1}

local _endline=${2}

local _filepath=${3}

log "author:"

cd ${FIRELINE_SCAN_SRC_DIR}

git blame -L ${_beginline},${_endline} ${_filepath}

if [[ $? -ne 0 ]]; then

finalize 1 "error: git blame -L ${_beginline},${_endline} ${_filepath} failed."

fi

}

function get_item_count_by_level () {

local _level=${1}

jq ".${_level} | length" ${FIRELINE_REPORT_JSON_FILE}

if [[ $? -ne 0 ]]; then

finalize 1 "error: get the count of <${_level}> level failed."

fi

}

function get_element_value_from_item () {

local _level=${1}

local _no=${2}

local _key=${3}

jq -r ".${_level}[] | select(.no == \"${_no}\") | .${_key}" ${FIRELINE_REPORT_JSON_FILE}

if [[ $? -ne 0 ]]; then

finalize 1 "error: get the key failed."

fi

}

function get_json_item_count () {

JSON_BLOCK_ITEM_COUNT=$( get_item_count_by_level 'block' )

JSON_ERROR_ITEM_COUNT=$( get_item_count_by_level 'error' )

}

function print_items_details () {

local _level=${1}

local _count=${2}

log "info: show the items of <${_level}>"

for ((i=1; i<=${_count}; i++)); do

_no=${i}

_classname=$( get_element_value_from_item ${_level} ${_no} 'classname' )

_filepath=$( get_element_value_from_item ${_level} ${_no} 'filepath' )

_rulename=$( get_element_value_from_item ${_level} ${_no} 'rulename' )

_rule_description=$( get_element_value_from_item ${_level} ${_no} 'ruleDescription' )

_docurl=$( get_element_value_from_item ${_level} ${_no} 'docurl' )

_beginline=$( get_element_value_from_item ${_level} ${_no} 'beginline' )

_endline=$( get_element_value_from_item ${_level} ${_no} 'endline' )

log "---- ${_no} ----"

log "classname: ${_classname}"

log "filepath: ${_filepath}"

log "rulename: ${_rulename}"

log "ruleDescription: ${_rule_description}"

log "docurl: ${_docurl}"

log "beginline: ${_beginline}"

log "endline: ${_endline}"

find_author_of_error_code ${_beginline} ${_endline} ${_filepath}

done

}

function main () {

# 初始化

init

# 1. git pull 更新扫描服务器上的代码

update_local_code

# 2. 执行火线静态代码扫描命令

fireline_scan

# 3. 发布火线扫描报告html

public_report_html

# 4. 检查火线扫描报告json文件内block和error条目的数量

get_json_item_count

# 5. 根据错误代码的文件名和出错行数查找错误代码作者

if [[ ${JSON_BLOCK_ITEM_COUNT}>0 ]]; then

log "fail: there are some code issues about level."

print_items_details 'block'${JSON_BLOCK_ITEM_COUNT}

else

log "info: not found the code issues about level."

fi

if [[ ${JSON_ERROR_ITEM_COUNT}>0 ]]; then

log "fail: there are some code issues about level."

print_items_details 'error' ${JSON_ERROR_ITEM_COUNT}

else

log "info: not found the code issues about level."

fi

}

main

脚本执行结果:

[root@VM-TEST-96 fireline]# bash /data/fireline/fireline.sh

##################################################

报告链接: http://www.17test.net/fireline/index_test.html

规则文档: http://magic.360.cn/document.html

##################################################

info: create new tmp report folder /tmp/report_test_20170904T201126

info: update the local code to the latest.

HEAD is now at e096a44 edit errot01 02 03

Counting objects: 15, done.

Compressing objects: 100% (6/6), done.

Writing objects: 100% (15/15), done.

Total 15 (delta 2), reused 15 (delta 2)

Already up-to-date.

info: fireline starts to scan the project of

info: fireline scans completely.

info: public the fireline report.

info: not found the code issues about level.

fail: there are some code issues about level.

info: show the items of

---- 1 ----

classname: TestFireline

filepath: /data/git/test/src/test/TestFireline.java

rulename: 错位的空判断

ruleDescription: 这里的空检查是放错位置的。如果变量为空你将得到一个空指针异常。可能因为检查是无用的或者是不正确的。如:if (!string.equals("") && string!=null){}。

docurl: http://magic.360.cn/document.html#CodeStyle-11

beginline: 53

endline: 53

author:

013d7a2d (binwei.liu 2017-09-04 15:39:29 +0800 53) if (a.equals(baz) && a != null) {}

---- 2 ----

classname: TestFireline

filepath: /data/git/test/src/test/TestFireline.java

rulename: 破坏空判断

ruleDescription: 如果自身抛出空指针异常空检查就会遭到破坏,比如你使用 代替 &&,反之亦然,如(应是&&):if (string!=null !string.equals("")){}。

docurl: http://magic.360.cn/document.html#CodeStyle-13

beginline: 60

endline: 62

author:

e096a440 (binwei.liu 2017-09-04 16:16:25 +0800 60) if (string!=null || !string.equals("")) {

e096a440 (binwei.liu 2017-09-04 16:16:25 +0800 61) return string;

e096a440 (binwei.liu 2017-09-04 16:16:25 +0800 62) }

---- 3 ----

classname: TestFireline

filepath: /data/git/test/src/test/TestFireline.java

rulename: 破坏空判断

ruleDescription: 如果自身抛出空指针异常空检查就会遭到破坏,比如你使用 代替 &&,反之亦然,如(应是&&):if (string!=null !string.equals("")){}。

docurl: http://magic.360.cn/document.html#CodeStyle-13

beginline: 65

endline: 67

author:

e096a440 (binwei.liu 2017-09-04 16:16:25 +0800 65) if (string==null && string.equals("")) {

e096a440 (binwei.liu 2017-09-04 16:16:25 +0800 66) return string;

e096a440 (binwei.liu 2017-09-04 16:16:25 +0800 67) }

[root@VM-TEST-96 fireline]#

火线 json 报告内容(/data/webtest/fireline/index_test.json):

{

"block": [],

"error": [

{

"no": "1",

"classname": "TestFireline",

"filepath": "/data/git/test/src/test/TestFireline.java",

"rulename": "错位的空判断",

"ruleDescription": "这里的空检查是放错位置的。如果变量为空你将得到一个空指针异常。可能因为检查是无用的或者是不正确的。如:if (!string.equals(\"\") && string!=null){}。",

"docurl": "http://magic.360.cn/document.html#CodeStyle-11",

"beginline": "53",

"endline": "53"

},

{

"no": "2",

"classname": "TestFireline",

"filepath": "/data/git/test/src/test/TestFireline.java",

"rulename": "破坏空判断",

"ruleDescription": "如果自身抛出空指针异常空检查就会遭到破坏,比如你使用 代替 &&,反之亦然,如(应是&&):if (string!=null !string.equals(\"\")){}。",

"docurl": "http://magic.360.cn/document.html#CodeStyle-13",

"beginline": "60",

"endline": "62"

},

{

"no": "3",

"classname": "TestFireline",

"filepath": "/data/git/test/src/test/TestFireline.java",

"rulename": "破坏空判断",

"ruleDescription": "如果自身抛出空指针异常空检查就会遭到破坏,比如你使用 代替 &&,反之亦然,如(应是&&):if (string!=null !string.equals(\"\")){}。",

"docurl": "http://magic.360.cn/document.html#CodeStyle-13",

"beginline": "65",

"endline": "67"

}

]

}

鸣谢: @oggboy (丁老九), 完善了火线 json 报告,使代码扫描和定位责任人两部分结合起来, 实现完整的自动化。

Copyright © 2088 世界杯直播cctv5_世界杯阿根 - sunjianping.com All Rights Reserved.
友情链接
top