小团队Code Review实践

引入Code Review的想法,预谋已久。除了希望提高代码质量之外,还有以下目的:

  • 提前发现代码中的低端错误和潜在Bug
  • 培养开发者良好的编程习惯,促进技术提高

工具选取

由于项目本身已经托管在内网的Gitlab上,所以优先考虑的是直接利用Gitlab为平台进行代码Review。Gitlab官网演示了基本的代码Review流程,基本流程如下:

  • 开发者在Feature分支上修改代码,需要提交时,新建Merge Request,指定Review人员
  • Review人员收到Merge Request后,进行代码Review
  • Review通过,Merge Request指派给具有合并分支权限的人员进行Merge
  • Review不通过,拒绝Merge Request,重复上述步骤

这一套流程实践下来的问题是:

  • 每次Push代码之后需要开发者手动创建Merge Request(当然可以通过脚本进行自动化,但需要额外配置),然后进行代码Review,不是很方便。
  • 团队内使用标准的Git Flow,大量开发工作在Feature分支进行。Gitlab无法对每个新建的Feature分支自动添加权限控制,也就无法强制对Feature分支进行Code Review。

在Gitlab无法满足团队需求的情况下,继续寻找替代方案。目前比较流行的Code Review平台,主要是Google出品的Gerrit和Facebook出品的Phabricator,二者都已开源。

Phabricator对比Gerrit有如下优势:

  • 界面美观(在工具使用非常频繁的情况下,美观度也是非常重要的)
  • 功能齐全(Phabricator除了代码托管和Code Review之外,还集成了任务、Wiki、日程等)
  • 提供两种不同的Review方式,团队可以灵活切换
  • 能够集成各种自动化插件

当然,Phabricator相对Gitlab也有缺点:

  • 代码托管方面不如Gitlab专业(也不弱,但不够专业)
  • 部署和使用成本较高(环境配置复杂,命令行较多,对于非开发人员使用成本较高)

但这些缺点对研发团队来说都不是硬伤,可以想办法解决,所以最后决定使用Phabricator。

Phabricator实战

服务端部署

服务端的部署主要由运维团队支持,这里就不详细介绍了(如有需求,后续由运维团队进行详细介绍)。部署成功后界面如下:

Web端功能简介

Phabricator支持Code Review、任务、代码托管、审计、Wiki等各种协同开发工具,非常适合小团队使用。

安装客户端环境

Phabricator Code Review需要两个库支持:

1
2
3
4
mkdir ~/phabricator
cd ~/phabricator
git clone https://github.com/phacility/arcanist.git
git clone https://github.com/phacility/libphutil.git

arcanist 主要用来做代码的修改和提交,libphutil 是配套工具库,用来做代码语法检查等。安装完成后,设置环境变量,方便全局使用 arc 命令

1
export PATH=$PATH:"~/phabricator/arcanist/bin/arc"

这样客户端环境就搭建完成了。

初始化设置

  • 创建Admin账号,默认第一个登录的为Admin
  • 设置用户的注册规则和登录认证方式(注册设置为只能以公司域名结尾的邮箱才能注册,登录采用用户名+密码的认证方式,依据实际情况设置)
  • 设置服务端邮件发送参数(后续所有的Review信息都会通过邮件通知)
  • 设置代码仓库读写方式(支持SSH方式,用户需要在设置里上传自己的SSH公钥,支持HTTP方式,需要设置拉取代码必须的VCS密码)

仓库管理

设置完成后,开始迁移旧仓库代码,首先在Phabricator上创建新仓库


编辑URIs:


将 I/O 修改为 No I/O。

选择New URI添加旧代码的git仓库地址,I/O Type选择Observe模式。

右边Set Credential添加SSH认证(有效公钥)或者HTTP认证(有拉取旧代码权限的用户名和密码)


设置好仓库之后,回到Basics页面,在Actions中选择Activate Repository激活仓库。

如果参数都正常的话,过一段时间就会将原仓库的代码都同步到Phabricator服务器上。

同步完成后,将新仓库代码 clone 到本地。如果代码在本地已经存在,需要修改remote url指向新的url:

1
git remote set-url origin ssh://domain/testdemo.git

同时在仓库中添加配置文件 .arcconfig,.arcconfig 文件是一个放置在项目的根目录的 JSON 文件。:

1
2
3
{
"phabricator.uri" : "http://your.phabricator.domain"
}

也可以设置全局的配置 etc/arcconfig,如果本地仓库没有配置文件,默认会读取全局配置。
这里只设置了 phabricator.uri(安装 Phabricator 的 URI),其他详细用法可参考官方文档。

配置Herald强制代码Reivew

如果希望所有的代码提交都需要Review,可以添加Herald规则。创建新的Herald Rule


设置好规则,如果没有提交过Differential Revision,禁止Push代码到服务器。

Review流程

传统的Review流程:

  • 开发者修改代码(Write)
  • 本地提交代码(Commit)
  • Push到服务器(Publish)
  • 代码审核(Review)
  • 通过或者拒绝(Merge or Refuse)

Phabricator本身也支持这种Review方式,主要是通过Audit进行提交后Review。这种流程大家都比较熟悉,在这里不做重点介绍,主要介绍另一种Review方式:

  • 开发者修改代码(Write)
  • 本地提交代码(Commit)
  • 预审核(Pre-Preview)
  • 提交审核通过(Merge -> Publish)
  • 提交被拒绝(Refuse)

以Feature分支为例,修改代码,本地提交,Push到远程仓库。由于前面设置了强制Review,所以直接Push会报权限错误:

Phabricator通过 arcanist 进行代码Review,详细用法可以使用arc help命令查看。先用 diff 命令生成Revision:
arc diff

填好Reviewers,如果需要通知其他人,填好Subscribers。如果本地有 .arclint 文件,diff 过程首先会调用 lint 脚本进行代码分析,生成编译错误或者警告。可以通过 arc linters 命令查看默认支持的 linter,也可以支持第三方或者自己开发的 linter。lint 检查通过后会生成Revision URI:


同时,如果之前邮件系统已经配置好,Reviewers和Subscribers都会收到邮件。在浏览器中打开URI,可以看到相关的修改


评论之后,选择Accept Revision,然后提交。Revision状态会变为Accepted,其他人的列表中变为Ready to Land状态。

表示Revision Review通过,等待开发者执行 land 命令,提交到远程仓库Merge。开发者收到Review通过的邮件之后,在本地执行 arc land --onto feature/test1 将代码提交到远程仓库。–onto 后面指定需要Merge的远程分支名,如果不填,默认为 master。

land 之后的代码就成功进入了远程仓库,整个Review过程结束。

关于代码格式化

对于提交仓库的代码是否需要格式化,目前有2种方式:

第一种是在代码进入远程仓库后,通过自动化脚本进行格式化。这是最可靠的格式化方式,但缺点是格式化代码会对部分提交进行修改,造成代码中会多很多冗余的提交,同时修改代码之后还需要自动化系统来保证编译的正确性。

第二种是在客户端预埋脚本,提交代码时如果不符合规范,无法提交成功。这种方式会比第一种方式风险小,但是覆盖面不够广,必须依赖每个客户端都安装脚本。同时格式化脚本的接入,会提高代码提交成本。想想有时候因为部分代码风格的问题,导致代码迟迟不能入库,也是一件很烦人的事(Xcode提供 crtl+i 的快捷方式进行代码格式调整)。

总之,两种方法都有弊病,具体如何抉择,由团队内部根据实际情况来选择。

代码Review控制

Web方式Review代码的缺点是不适合Review大块代码,同时也没办法像IDE一样进行调试。所以尽量是控制每次提交的量代码量,每天提交代码进行Review。如果积攒了几个月的代码一次性提交,审核者也是一头包,Review效率也会大幅下降。

同一个功能最好是由同一个人Review,这样能保证业务的熟练度和细节的Review粒度。也提倡互相Review代码,而不是长期由Leader或者高级工程师Review,促进所有开发人员的技术成长。

后续目标

参考链接:

Phabricator

Phabricator Review Workflow

Phabricator中文站

使用Phabricator做为Code Review工具

大家的公司的Code Review都是怎么做的?遇到过哪些问题?