介绍
作为一名从业多年的后端开发人员,已经逐渐减少了自己写代码的时间,将更多的工作时间投入到 code review 中。通过 code review 可以减少 bug 出现的概率,提高代码质量,还可以帮助他人进步。
但在 code review 的过程中,会发现有些人的编码习惯不太好,导致代码结构、格式混乱,代码里面暗藏深坑。比如:
方法过长,把整个逻辑都写在一个方法里面,没有进行必要的抽象与封装。
方法没有必要注释,方法名还做不到望文生义。
文件打开以后,忘记关闭工作流。
等等情况。
我在 code review 的过程中,能够发现一些问题,但还有一些问题,也许是大意,也许是知识不够全面,可能就被遗漏了。
每次光是格式和编码习惯的检查就会占用大量 code review 时间,这种状况令人十分苦恼。
有没有一种可能,在我 code review 之前,自动把格式规范,编码习惯这些简单的问题都检查完成,告诉我一个检查结果,我只需要去 review 业务代码呢?
后来我发现了建木 + checkstyle + SonarQube。
组件介绍
建木:建木以触发器、流程编排、任务分发等功能为核心,可以应用在各类使用场景下,包括但不限于,CI/CD、DevOps、自动化运维、多业务系统集成等场景。在我的使用过程中,发现它十分灵活,可以自由组合各种功能,使用也十分简单,只要选好你心仪的节点,把它加入到你的流程中就 OK 啦。
整体使用流程
如图:
流程讲解:
Coder 将自己的代码提交到代码仓库,发起 Merge Request。
代码仓库调用建木钩子,触发建木流程。
建木从仓库拉取代码,进行 checkstyle 和 SonarQube 静态代码扫描。
建木将扫描结果,以评论的方式,写回到 Merge Request 的评论中。
Reviewer 开始工作,参考扫描结果,进行 Code Review。
自此,code review 也有了“自动档”,有建木辅助 merge 的检查,点 merge 更有底气~
如何搭建
下面和大家分享一下如何使用建木来搭建这个流程🤓
对项目本身进行改造,在项目中引入 checkstyle 和 SonarQube 插件,并完成配置工作。关于 checkstyle 和 sonarqube 的配置使用可以参考:checkstyle官方文档SonarQube官方文档
开始准备我们需要使用到的建木节点🤪
克隆源分支和目标分支代码。
执行 mvn compile sonar:sonar 来检查代码是否存在缺陷
执行 mvn checkstyle:checkstyle-aggregate 来检查代码是否规范
比较源分支和目标分支的规范结果文件,结果大于 0,说明本次合并新增加了不规范代码
注:checkstyle 的扫描已经配置在执行 maven 命令时自动执行,check_style 节点,只是用来获取分析 maven 执行日志中的扫描结果。
获取本次代码新增 BUG 和新增漏洞的数量,以及获取 sonarqube 的部署地址。
注:SonarQube 的扫描已经配置在执行 maven 命令时自动执行,SonarQube 节点,只是用来获取 maven 执行日志中的扫描结果。
向 Gitlab 的 Merge Request 中以评论方式通知扫描结果。
发送相关通知到企业微信。
然后编写 DSL 文件
name: java-style-check
# 可并发执行
global:
concurrent: true
trigger:
type: webhook
param:
- name: action
type: STRING
exp: $.body.json.object_attributes.action
- name: object_kind
type: STRING
exp: $.body.json.object_kind
- name: user_name
type: STRING
exp: $.body.json.object_attributes.last_commit.author.name
- name: project_name
type: STRING
exp: $.body.json.project.name
- name: source_branch
type: STRING
exp: $.body.json.object_attributes.source_branch
- name: target_branch
type: STRING
exp: $.body.json.object_attributes.target_branch
- name: remote_url
type: STRING
exp: $.body.json.project.git_http_url
- name: git_host
type: STRING
exp: $.header.x-real-ip
- name: project_id
type: STRING
exp: $.body.json.project.id
- name: iid
type: STRING
exp: $.body.json.object_attributes.iid
# webhook事件 一个merge事件open、update、reopen都可以触发该流程
only: (${trigger.object_kind} == "merge_request" && ${trigger.action} == "open" || ${trigger.action} == "update" || ${trigger.action} == "reopen")
workflow:
start:
type: start
targets:
- git_source_branch
- git_target_branch
# 源分支
git_source_branch:
type: "git_clone:1.1.1"
sources:
- start
targets:
- maven1
param:
remote_url: "${trigger.remote_url}"
ref: "refs/heads/${trigger.source_branch}"
netrc_password: "((gitlab.password))"
netrc_machine: "x.x.x.x"
netrc_username: "((gitlab.username))"
# 通过mvn命令,使用代码规范检查工具check-style检查源分支,生成规范结果文件
# 通过mvn命令,使用代码缺陷检查工具sonarqube来检查代码,并且把结果上传到服务器
maven1:
type: "jianmu/maven:jdk"
sources:
- git_source_branch
targets:
- sonarqube_analysis
param:
mvn_action: "compile sonar:sonar clean checkstyle:checkstyle-aggregate"
workspace: "${git_source_branch.git_path}"
maven_public_id: "maven-releases"
maven_public_url: "http://x.x.x.x:8081/repository/maven-public/"
# 获取本次代码新增BUG和新增漏洞的数量,以及获取sonarqube的部署地址
sonarqube_analysis:
sources:
- maven1
targets:
- check_style
type: "fat_squirrel/sonarqube_analysis:v2"
param:
ip: "x.x.x.x:9000"
project_name: "name"
# 目标分支
git_target_branch:
type: "git_clone:1.2.2"
sources:
- start
targets:
- maven2
param:
remote_url: "${trigger.remote_url}"
ref: "refs/heads/${trigger.target_branch}"
password: "((gitlab.password))"
username: "((gitlab.username))"
# 使用代码规范检查工具check-style检查目标分支,生成规范结果文件
maven2:
type: "maven_build:1.3.1-jdk"
sources:
- git_target_branch
targets:
- check_style
param:
mvn_action: "checkstyle:checkstyle-aggregate"
workspace: "${git_target_branch.git_path}"
maven_public_id: "maven-releases"
maven_public_url: "http://172.16.35.15:8081/repository/maven-public/"
# 从共享目录中获取源分支和目标分支的规范结果文件进行比较
check_style:
sources:
- sonarqube_analysis
- maven2
targets:
- condition
type: "jianmu/check_style:v3"
param:
file2: "${git_target_branch.git_path}/target/checkstyle-result.xml"
file1: "${git_source_branch.git_path}/target/checkstyle-result.xml"
# 判断节点,走不同的分支
condition:
sources:
- check_style
type: condition
expression: ${check_style.result}=="1"
cases:
true: qywx_notice
false: condition2
qywx_notice:
type: "qywx_notice:1.2.1"
sources:
- condition
targets:
- git_merge_comment1
param:
mentioned_mobile_list: "[]"
bot_webhook_url: "((chatbot.merge))"
text_content: "项目:${trigger.project_name},提交人:${trigger.user_name},消息:本次提交增加了不符合规范数:${check_style.diff}"
msgtype: "text"
mentioned_list: "[]"
git_merge_comment1:
type: "jianmu/git_merge_comment:v1"
sources:
- qywx_notice
targets:
- end
param:
project_id: "${trigger.project_id}"
host: "${trigger.git_host}"
comment: "action:${trigger.action},项目:${trigger.project_name},提交人:${trigger.user_name},消息:本次合并新增${check_style.diff}个格式问题,新增${sonarqube_analysis.new_bugs}个bug风新增,新增${sonarqube_analysis.new_vulnerabilities}个漏洞问题,详情可见:'${sonarqube_analysis.url}'"
merge_request_iid: "${trigger.iid}"
token: "((AUTOOPS.private_token))"
condition2:
sources:
- condition
type: condition
expression: ${check_style.result}=="0"
cases:
true: qywx_notice2
false: qywx_notice3
qywx_notice2:
type: "qywx_notice:1.2.1"
sources:
- condition2
targets:
- git_merge_comment2
param:
mentioned_mobile_list: "[]"
bot_webhook_url: "((chatbot.merge))"
text_content: "项目:${trigger.project_name},提交人:${trigger.user_name},消息:本次提交不多不少,正正好好!"
msgtype: "text"
mentioned_list: "[]"
git_merge_comment2:
type: "jianmu/git_merge_comment:v1"
sources:
- qywx_notice2
targets:
- end
param:
project_id: "${trigger.project_id}"
host: "${trigger.git_host}"
comment: "action:${trigger.action},项目:${trigger.project_name},提交人:${trigger.user_name},消息:本次合并无新增格式问题,新增${sonarqube_analysis.new_bugs}个bug风新增,新增${sonarqube_analysis.new_vulnerabilities}个漏洞问题,详情可见:'${sonarqube_analysis.url}'"
merge_request_iid: "${trigger.iid}"
token: "((AUTOOPS.private_token))"
qywx_notice3:
type: "qywx_notice:1.2.1"
sources:
- condition2
targets:
- git_merge_comment3
param:
mentioned_mobile_list: "[]"
bot_webhook_url: "((chatbot.merge))"
text_content: "项目:${trigger.project_name},提交人:${trigger.user_name},消息:本次提交减少了不符合规范数:${check_style.diff}"
msgtype: "text"
mentioned_list: "[]"
git_merge_comment3:
type: "jianmu/git_merge_comment:v1"
sources:
- qywx_notice3
targets:
- end
param:
project_id: "${trigger.project_id}"
host: "${trigger.git_host}"
comment: "action:${trigger.action},项目:${trigger.project_name},提交人:${trigger.user_name},消息:本次合并减少${check_style.diff}个格式问题,新增${sonarqube_analysis.new_bugs}个bug风新增,新增${sonarqube_analysis.new_vulnerabilities}个漏洞问题,详情可见:'${sonarqube_analysis.url}'"
merge_request_iid: "${trigger.iid}"
token: "((AUTOOPS.private_token))"
end:
type: end
sources:
- git_merge_comment1
- git_merge_comment2
- git_merge_comment3
复制代码
DSL 编写完以后,总流程它长这样🤩。
触发流程
从建木中复制触发链接,在 Gitlab 中配置 Merge Request 的 Webhook,将从建木复制的链接粘贴进去。当有人发起 Merge Request 时,就会触发流程了。
结果展示
结尾
在使用建木 + checkstyle + SonarQube 以后,工作的效率大大提高了,有更多的时间去完成更有意义的事情,毕竟人生苦短!
官⽹
代码
文档
示例
评论