使用Phabricator做為Code Review工具

目錄

  • 0x10 概述
  • 0x20 我的應(yīng)用環(huán)境
  • 0x30 路線(xiàn)圖
  • 0x40 安裝
    0x41 LNMP環(huán)境的安裝
    0x42 Phabricator源碼下載及運(yùn)行
  • 0x50 配置
    0x51 解決基本的配置問(wèn)題
    0x52 設(shè)置用戶(hù)登錄認(rèn)證方式
    0x53 設(shè)置郵件發(fā)送服務(wù)參數(shù)
    0x54 配置代碼倉(cāng)庫(kù)訪(fǎng)問(wèn)方式:SSH/HTTP
  • 0x60 使用Phabricator進(jìn)行Code Review
    0x61 Phabricator Code Review工作流
    0x62 進(jìn)行Code Review所用工具
    0x63 配置進(jìn)行Code Review
  • 0x70 與GitHub集成
  • 0x80 與Jenkins集成
  • 0x90 結(jié)束語(yǔ)
  • 0xA0 Q/A

0x10 概述

Phabricator是一套基于Web的軟件開(kāi)發(fā)協(xié)作工具,包括代碼審查工具Differential,資源庫(kù)瀏覽器Diffusion,變更監(jiān)測(cè)工具Herald,Bug跟蹤工具M(jìn)aniphest和維基工具Phriction。Phabricator可與Git、Mercurial、Subversion集成使用。
Phabricator是開(kāi)源軟件,可在A(yíng)pache許可證第2版下作為自由軟件分發(fā)。
Phabricator最初是Facebook的一個(gè)內(nèi)部工具,主要開(kāi)發(fā)者為Evan Priestley。Evan Priestley離開(kāi)Facebook后,在名為Phacility的新公司繼續(xù)Phabricator的開(kāi)發(fā)。

官網(wǎng):https://www.phacility.com/

官網(wǎng)中的文檔很多很全,但是如果對(duì)這個(gè)工具不太了解,或者對(duì)于Code Review不太了解的話(huà),讀起來(lái)可能會(huì)覺(jué)得沒(méi)有頭緒。這篇文章就自己的安裝及使用過(guò)程做一個(gè)梳理,對(duì)于同樣想用這個(gè)工具的讀者,或許起到一些幫助作用。
對(duì)于本文中的一些章節(jié),如果在官方文檔有所提及,我會(huì)把官方文檔地址附上,讀者可以閱讀一下官方文檔,因?yàn)樗麄兊恼Z(yǔ)言和表達(dá)更優(yōu)秀。

0x20 我的應(yīng)用環(huán)境

  • 我:一個(gè)做了很多年Android的程序員 (所以當(dāng)這篇文章有幸被所涉及領(lǐng)域的專(zhuān)家看到,又發(fā)現(xiàn)有的部分有所不妥,或者有更好的想法時(shí),請(qǐng)主動(dòng)聯(lián)系我改進(jìn),多謝~~~ 有任何問(wèn)題,歡迎評(píng)論交流)
  • 主機(jī):Ubuntu 14.04 PC一臺(tái)
  • 網(wǎng)絡(luò):內(nèi)網(wǎng)
  • 代碼庫(kù):GitHub
  • CI:Jenkins

0x30 路線(xiàn)圖

安裝和使用路線(xiàn)大致如此圖,下面開(kāi)始詳細(xì)說(shuō)明。

0x40 安裝

Phabricator是一個(gè)基于Web的工具軟件,使用PHP語(yǔ)言編寫(xiě)的,為了能讓他運(yùn)行起來(lái),我們需要搭建一個(gè)LNMP(Linux,Nginx,MySQL,PHP)的Web Server環(huán)境。搭建完LNMP的環(huán)境后,下載Phabricator源碼,配置后即可使用。

  • 先看我
    如果你不想讀那么多文字,在Ubuntu環(huán)境下可以試試下面的腳本,這個(gè)腳本可以安裝LNMP環(huán)境和下載Phabricator源碼,執(zhí)行完腳本并成功后,跳到 0x42 Phabricator源碼下載及運(yùn)行 查看如何讓Phabricator跑起來(lái)。
#!/bin/bash
 
confirm() {
  echo "Press RETURN to continue, or ^C to cancel.";
  read -e ignored
}
 
GIT='git'
 
LTS="Ubuntu 10.04"
ISSUE=`cat /etc/issue`
if [[ $ISSUE != Ubuntu* ]]
then
  echo "This script is intended for use on Ubuntu, but this system appears";
  echo "to be something else. Your results may vary.";
  echo
  confirm
elif [[ `expr match "$ISSUE" "$LTS"` -eq ${#LTS} ]]
then
  GIT='git-core'
fi
 
echo "PHABRICATOR UBUNTU INSTALL SCRIPT";
echo "This script will install Phabricator and all of its core dependencies.";
echo "Run it from the directory you want to install into.";
echo
 
ROOT=`pwd`
echo "Phabricator will be installed to: ${ROOT}.";
confirm
 
echo "Testing sudo..."
sudo true
if [ $? -ne 0 ]
then
  echo "ERROR: You must be able to sudo to run this script.";
  exit 1;
fi;
 
echo "Installing dependencies: git, nginx, mysql, php...";
echo
 
set +x
 
sudo apt-get -qq update
sudo apt-get install \
  $GIT nginx mysql-server dpkg-dev \
  php5 php5-mysql php5-gd php5-dev php5-curl php-apc php5-cli php5-json
 
# Enable mod_rewrite
sudo a2enmod rewrite
 
HAVEPCNTL=`php -r "echo extension_loaded('pcntl');"`
if [ $HAVEPCNTL != "1" ]
then
  echo "Installing pcntl...";
  echo
  apt-get source php5
  PHP5=`ls -1F | grep '^php5-.*/$'`
  (cd $PHP5/ext/pcntl && phpize && ./configure && make && sudo make install)
else
  echo "pcntl already installed";
fi
 
if [ ! -e libphutil ]
then
  git clone https://github.com/phacility/libphutil.git
else
  (cd libphutil && git pull --rebase)
fi
 
if [ ! -e arcanist ]
then
  git clone https://github.com/phacility/arcanist.git
else
  (cd arcanist && git pull --rebase)
fi
 
if [ ! -e phabricator ]
then
  git clone https://github.com/phacility/phabricator.git
else
  (cd phabricator && git pull --rebase)
fi
 
echo
echo
echo "Install probably worked mostly correctly. Continue with the 'Configuration Guide':";
echo
echo "    https://secure.phabricator.com/book/phabricator/article/configuration_guide/";
echo
echo "You can delete any php5-* stuff that's left over in this directory if you want.";

關(guān)于安裝和配置,官方文檔中有所提及(官方介紹的是 LAMP),請(qǐng)參考

https://secure.phabricator.com/book/phabricator/article/installation_guide/

0x41 LNMP環(huán)境的安裝
  • 安裝Linux
    關(guān)于Linux的安裝,這里就不說(shuō)了。

  • 安裝Nginx

sudo apt-get install nginx

安裝完成后,Nginx 的配置文件存放在 /etc/nginx 目錄下。使用下面的命令可以啟動(dòng)Nginx

sudo service nginx start

在安裝完并啟動(dòng)后,可以使用瀏覽器訪(fǎng)問(wèn) http://127.0.0.1 試試是否可以跳轉(zhuǎn)到Nginx歡迎頁(yè)面

  • 安裝MySQL

    sudo apt-get install mysql-server
    

    在安裝過(guò)程中,會(huì)兩次提示輸入 root 用戶(hù)密碼。
    在安裝完成后,打開(kāi)終端,使用以下命令登錄MySQL

    mysql -u root -p
    
  • 安裝PHP
    Phabricator需要 PHP 5.2 或者更高版本,但是 不支持 PHP 7
    可以使用以下命令安裝PHP

sudo apt-get install -y php5 php5-fpm php5-mysql

安裝完成后,可使用以下命令查看是否安裝成功

 php -v

安裝成功后,輸出類(lèi)似以下信息

  • 安裝其它
    如果你使用 git 來(lái)管理代碼庫(kù)的話(huà),你還需要安裝 git
sudo apt-get install git

一些必要的PHP擴(kuò)展

mbstring, iconv, mysql (or mysqli), curl, pcntl(這些擴(kuò)展一般會(huì)以 "php-mysql""php5-mysql" 方式使用)

一些可選的PHP擴(kuò)展

gd, apc(官方文檔中有詳細(xì)的介紹和安裝說(shuō)明), xhprof(如果你想自己開(kāi)發(fā)Phabricator的話(huà),你需要安裝這個(gè),官方文檔中有詳細(xì)的介紹說(shuō)明)

0x42 Phabricator源碼下載及運(yùn)行

在成功安裝LNMP環(huán)境后,需要下載Phabricator的源碼并配置讓它跑起來(lái)。

  • 源碼下載
    在你想要存放Phabricator源碼的位置(假設(shè)為 ./path_to_pha),執(zhí)行這些命令
git clone https://github.com/phacility/libphutil.git
git clone https://github.com/phacility/arcanist.git
git clone https://github.com/phacility/phabricator.git

或者,你也可以直接點(diǎn)擊上面的鏈接去GitHub下載壓縮包,下載完成后解壓。

  • Nginx配置
    在下載完成后,我們需要配置Nginx,讓Phabricator跑起來(lái)。假設(shè)你想為Phabricator分配這個(gè)域名:http://pha.example.com
    /etc/nginx/conf.d 目錄下創(chuàng)建文件 pha.example.com.conf,存放Phabricator代理配置信息,以下為我的文件內(nèi)容(注意把 你存放Phabricator的路徑 改為你的實(shí)際路徑)
server {
    listen       80;
    server_name  pha.example.com; 
    location / {
        index index.php;
        rewrite ^/(.*)$ /index.php?__path__=/$1 last;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

     # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    location ~ \.php$ {
        root           /你存放Phabricator的路徑/phabricator/webroot;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /你存放Phabricator的路徑/phabricator/webroot$fastcgi_script_name;
        include        fastcgi_params;
    }
}

配置完成后,重啟Nginx

sudo service nginx restart

然后在你的 hosts 文件中,加入 pha.example.com 對(duì)應(yīng)的IP

127.0.0.1 pha.example.com

打開(kāi)瀏覽器,訪(fǎng)問(wèn) http://pha.example.com,會(huì)跳轉(zhuǎn)到Phabricator用戶(hù)注冊(cè)界面,在這個(gè)界面注冊(cè)的第一個(gè)用戶(hù),將會(huì)成為管理員用戶(hù)。

0x50 配置

0x51 解決基本的配置問(wèn)題

使用管理員賬號(hào)登錄,左上角會(huì)出現(xiàn)黃色感嘆號(hào)圖標(biāo),提示有一些配置問(wèn)題未解決


這些問(wèn)題基本都是關(guān)于一些參數(shù)的設(shè)置。點(diǎn)擊每一個(gè)問(wèn)題,顯示的界面中會(huì)有很詳細(xì)的關(guān)于這個(gè)問(wèn)題的描述,和如何解決。

0x52 設(shè)置用戶(hù)登錄認(rèn)證方式

使用管理員賬號(hào)登錄,在左側(cè)的菜單中選擇 Auth ,然后點(diǎn)擊右上側(cè) Add Provider,在列表中選則你需要的認(rèn)證方式。

我選擇是 Username/Password 的方式,即用戶(hù)自己注冊(cè)Phabricator賬號(hào)。為了保障安全,我設(shè)置了只允許公司郵箱地址注冊(cè):Config ---> Core Settings ---> ** Authentication** ---> auth.email-domains。你還可以選擇 auth.require-approval ,即新注冊(cè)用戶(hù)需要管理員批準(zhǔn)。

0x53 設(shè)置郵件發(fā)送服務(wù)參數(shù)

首先,配置 mail-adapter (郵件發(fā)送方式):Config ---> Core Settings ---> Mail ---> metamta.mail-adapter,我選擇的是 PhabricatorMailImplementationPHPMailerAdapter ,通過(guò)SMTP的方式發(fā)送郵件。在選擇完之后,需要設(shè)置SMTP服務(wù)器地址、賬號(hào)和密碼:Config ---> Core Settings ---> PHPMailer ---> metamta.mail-adapter,根據(jù)你自己郵箱的配置,相應(yīng)的設(shè)置 phpmailer.smtp-hostphpmailer.smtp-portphpmailer.smtp-protocolphpmailer.smtp-userphpmailer.smtp-passwordphpmailer.smtp-encoding

0x54 配置代碼倉(cāng)庫(kù)訪(fǎng)問(wèn)方式:SSH/HTTP
  • SSH
    (如果你不打算允許使用SSH的方式訪(fǎng)問(wèn)代碼倉(cāng)庫(kù)的話(huà),請(qǐng)忽略這部分)
    1)配置用戶(hù)賬號(hào)
    Phabricator需要三個(gè)用戶(hù)賬號(hào)(三種用戶(hù)身份):兩個(gè)用于基本運(yùn)行,一個(gè)用于配置SSH訪(fǎng)問(wèn)。這些賬號(hào)是指Phabricator所運(yùn)行服務(wù)器系統(tǒng)的賬號(hào),不是Phabricator用戶(hù)賬號(hào)。
    三個(gè)賬號(hào)分別是:
    www-user:Phabricator Web服務(wù)器運(yùn)行身份。
    daemon-user :daemons (守護(hù)進(jìn)程)運(yùn)行身份。這個(gè)賬號(hào)是唯一直接與代碼倉(cāng)庫(kù)交互的賬號(hào),其它賬號(hào)需要切換到這個(gè)賬號(hào)身份(sudo)才能操作代碼倉(cāng)庫(kù)。
    vcs-user:我們需要以這個(gè)賬號(hào)SSH連接Phabricator。
    如果你的服務(wù)器系統(tǒng)中現(xiàn)在沒(méi)有這三個(gè)賬號(hào),需要?jiǎng)?chuàng)建:
    www-user:大部分情況下,這個(gè)賬號(hào)已經(jīng)存在了,我們不需要理這個(gè)賬號(hào)。
    daemon-user :一般情況下,我們直接使用 root 賬號(hào),因?yàn)闀?huì)需要很多權(quán)限(當(dāng)然這可能不安全)。
    vcs-user:可以使用系統(tǒng)中現(xiàn)有的一個(gè)用戶(hù)賬號(hào),直接創(chuàng)建一個(gè)就叫 vcsuser。當(dāng)用戶(hù)克隆倉(cāng)庫(kù)的時(shí)候,需要使用類(lèi)似 vcsuser@pha.example.com 的URI。
    2)配置Phabricator
    首先,設(shè)置 phd.userdaemon-user(root)
./path_to_pha/bin/config set phd.user root

重啟 daemons 以確認(rèn)這個(gè)配置工作正常

./path_to_pha/bin/phd restart

然后,配置SSH用戶(hù)賬號(hào)vcs-user(vcsuser 或其它你想用的用戶(hù))

./path_to_pha/bin/config set diffusion.ssh-user vcsuser

3)配置 Sudo
www-uservcs-user 需要能夠使用 sudo 切換到 daemon-user 用戶(hù)身份才能與倉(cāng)庫(kù)交互,所以我們需要配置更改系統(tǒng)的 sudo 配置。
直接編輯 /etc/sudoers 或者在 /etc/sudoers.d 下創(chuàng)建一個(gè)新文件,然后把這些內(nèi)容寫(xiě)到文件內(nèi)容中

www-user ALL=(root) SETENV: NOPASSWD: /usr/lib/git-core/git, /usr/bin/git, /var/lib/git, /usr/lib/git-core/git-http-backend, /usr/bin/ssh, /etc/ssh, /etc/default/ssh, /etc/init.d/ssh
vcs-user ALL=(root) SETENV: NOPASSWD: /bin/sh, /usr/bin/git-upload-pack, /usr/bin/git-receive-pack

當(dāng)然,別忘了把 www-user 和 vcs-user 替換為你實(shí)際對(duì)應(yīng)的用戶(hù)。
接下來(lái),看看你文件中是不是有這行

Defaults requiretty

如果有的話(huà),請(qǐng)用 # 注釋掉。

4)其它SSH配置
我們還需要查看這兩個(gè)文件 /etc/shadow/etc/passwdvcs-user 對(duì)應(yīng)的配置是否正確。
打開(kāi) /etc/shadow 文件,找到 vcs-user 對(duì)應(yīng)的那行,看一下第二個(gè)字段(密碼),是不是 !! ,如果是,請(qǐng)改為 空值(什么都不寫(xiě)) 或者 NP
打開(kāi) /etc/passwd 文件,找到 vcs-user 對(duì)應(yīng)的那行,如果有類(lèi)似于這樣的配置 /bin/false ,請(qǐng)修改為 /bin/sh,否則 sshd 無(wú)法執(zhí)行命令。

5)配置SSHD端口
注意:Phabricator運(yùn)行的服務(wù)器系統(tǒng)中 sshd 的版本 必須高于 6.2
假設(shè)我們把Phabricator使用的sshd端口設(shè)置為 22,這樣做的好處是我們不需要在倉(cāng)庫(kù)的URI中加入端口號(hào),類(lèi)似ssh://vcs-user@pha.example.com/xxx/xxx/xxx.git。當(dāng)然,如果這樣做需要我們更改系統(tǒng)已存在的sshd配置改為其它端口。下面來(lái)看一下配置的三個(gè)步驟:
i)創(chuàng)建腳本 phabricator-ssh-hook.sh,并且把這個(gè)腳本放到類(lèi)似 /usr/libexec/phabricator-ssh-hook.sh 的目錄中(我直接放在 /etc/ssh/ 中,后面會(huì)要求變更這個(gè)腳本和它的父文件夾所有者,所以這個(gè)腳本和它的父文件夾所在的文件夾的所有者不正確的話(huà)可能會(huì)導(dǎo)致這個(gè)腳本執(zhí)行失敗),腳本內(nèi)容如下

#!/bin/sh

# NOTE: Replace this with the username that you expect users to connect with.
VCSUSER="vcs-user"

# NOTE: Replace this with the path to your Phabricator directory.
ROOT="/path_to_pha"

if [ "$1" != "$VCSUSER" ];
then
  exit 1
fi

exec "$ROOT/bin/ssh-auth" $@

注意把 VCSUSER 替換為你實(shí)際的用戶(hù),把 ROOT 值替換為你Phabricator源碼路徑。
創(chuàng)建完腳本后,需要把腳本和它的父文件夾所有者改為 root,并且賦予腳本 755 權(quán)限:

sudo chown root /path/to/somewhere/
sudo chown root /path/to/somewhere/phabricator-ssh-hook.sh
sudo chmod 755 /path/to/somewhere/phabricator-ssh-hook.sh

如果你不這么做,sshd 會(huì)拒絕執(zhí)行 hook。

ii)為Phabricator創(chuàng)建 sshd_config
/etc/ssh 中創(chuàng)建文件名類(lèi)似 sshd_config.phabricator 的文件,文件內(nèi)容如下:

# NOTE: You must have OpenSSHD 6.2 or newer; support for AuthorizedKeysCommand
# was added in this version.

# NOTE: Edit these to the correct values for your setup.

AuthorizedKeysCommand /你的腳本路徑/phabricator-ssh-hook.sh
AuthorizedKeysCommandUser vcs-user
AllowUsers vcs-user

# You may need to tweak these options, but mostly they just turn off everything
# dangerous.

Port 你配置的端口號(hào)
Protocol 2
PermitRootLogin no
AllowAgentForwarding no
AllowTcpForwarding no
PrintMotd no
PrintLastLog no
PasswordAuthentication no
AuthorizedKeysFile none

PidFile /var/run/sshd-phabricator.pid

注意把 AuthorizedKeysCommand 值替換為你在上一步中腳本實(shí)際路徑,把 AuthorizedKeysCommandUserAllowUsers 替換為你實(shí)際的用戶(hù),把 Port 替換為你想配置的端口號(hào)。如果你的 Port 值為 22,在你進(jìn)行下面的操作之前,請(qǐng)查看當(dāng)前系統(tǒng)中 22 端口是已否占用

sudo netstat -atlunp | grep ssh

如果已經(jīng)被占用,請(qǐng)修改使用 22 端口的 sshd 配置,一般它們會(huì)在 /etc/ssh 下,名稱(chēng)類(lèi)似 sshd_config,修改完成后,請(qǐng)重啟 ssh 服務(wù)

sudo /etc/init.d/ssh restart

在完成上面的步驟后,我們來(lái)啟動(dòng)Phabricator的 ssh 服務(wù)

sudo /path/to/sshd -f /你的Phabricator sshd配置路徑/sshd_config.phabricator

一般情況下,sshd 路徑為 /usr/sbin
在啟動(dòng)后,我們需要驗(yàn)證以下配置是否有效:
首先,請(qǐng)把你的公鑰添加到Phabricator自己的賬號(hào)中(你可以自己注冊(cè)一個(gè)新的賬號(hào)),注冊(cè)完成后登錄,然后 點(diǎn)擊你的頭像 ---> 左側(cè)菜單面板 Manage ---> 右側(cè)菜單面板 Edit Settings ---> 左側(cè)菜單面板 SSH Public Keys ---> 右上角 SSH Key Actions ---> Upload Public Key

上傳公鑰后,執(zhí)行下面的命令

echo {} | ssh vcs-user@phabricator.yourcompany.com conduit conduit.ping

如果出現(xiàn)類(lèi)似下面的結(jié)果,說(shuō)明配置有效

{"result":"phabricator.yourcompany.com","error_code":null,"error_info":null}

如果沒(méi)有出現(xiàn)別的情況,請(qǐng)參考官方文檔 Troubleshooting SSH 部分,官方文檔地址如下

https://secure.phabricator.com/book/phabricator/article/diffusion_hosting/

接下來(lái),看一下如何配置 HTTP

  • HTTP
    首先,請(qǐng)確認(rèn)Phabricator的配置項(xiàng) diffusion.allow-http-auth 設(shè)置為 true。可以在 左側(cè)菜單面板 All Setttings 中查找 diffusion.allow-http-auth ,點(diǎn)擊之后可設(shè)置,請(qǐng)?jiān)O(shè)置為 Allow HTTP Basic Auth
    然后,所有用戶(hù)需要使用 HTTP 訪(fǎng)問(wèn)倉(cāng)庫(kù)之前,需要設(shè)置自己的密碼:點(diǎn)擊你的頭像 ---> 左側(cè)菜單面板 Manage ---> 右側(cè)菜單面板 Edit Settings ---> 左側(cè)菜單面板 VCS Password

強(qiáng)烈建議不要把這個(gè)密碼設(shè)置為你的Phabricator登錄密碼,因?yàn)?vcs 密碼很容易泄露。
一般來(lái)說(shuō),不需要其它配置就可以使用 HTTP 了,如果有問(wèn)題,請(qǐng)參考官方文檔 Troubleshooting HTTP 部分

https://secure.phabricator.com/book/phabricator/article/diffusion_hosting/

配置完倉(cāng)庫(kù)訪(fǎng)問(wèn)方式后,我們來(lái)看一下如何使用 Phabricator 進(jìn)行 Code Review。

0x60 使用Phabricator進(jìn)行Code Review

在進(jìn)行 Code Review 實(shí)踐前,先說(shuō)一些理論方面的東西(開(kāi)頭和 0x61 ,不喜歡可繞過(guò))
Code Review,有時(shí)候就像打架一樣:我提交了變更,你說(shuō)不行,要修改;我又提交了一次,你說(shuō)還是不行,還要改。我不知道你究竟要怎樣,你也不知道我感覺(jué)受到了打擊有多不爽。所以,大家需要對(duì)Code Review這件事抱有開(kāi)放的態(tài)度:

  • 為什么我的代碼需要其他人審查?
    因?yàn)槲也皇巧瘢視?huì)制造Bug,我會(huì)當(dāng)局者迷。
  • 為什么我要審查其他人的代碼?
    因?yàn)槲乙獙?duì)我們的團(tuán)隊(duì)負(fù)責(zé),我要保證我們產(chǎn)品的質(zhì)量,我可能會(huì)看到他人代碼的Bug,在這些Bug顯示出它們的"威力"前,把它們弄死。

Code Review這件事,旨在創(chuàng)造一個(gè)共進(jìn)的團(tuán)隊(duì)氛圍(交流和技術(shù)等),在產(chǎn)品交付給用戶(hù)(包括我們的測(cè)試人員)前,保證產(chǎn)品的質(zhì)量。

在了解如何使用Phabricator進(jìn)行Code Review前,我們先了解一下Phabricator Code Review的流程,對(duì)其有一個(gè)整體上的了解。

0x61 Phabricator Code Review工作流

Phabricator提供兩種Code Review的方式:pre-pushpost-push
pre-push 是指審查發(fā)生在變更發(fā)布前;post-push 是指審查發(fā)生在變更已經(jīng)被發(fā)布或者正在發(fā)布。
這里我們認(rèn)為 pre-push 的方式更適合,所以接下來(lái)說(shuō)一下 pre-push 的工作流:

Write, Review, Merge, Publish

從這篇文章,我了解到了這個(gè)流程

https://secure.phabricator.com/phame/post/view/766/write_review_merge_publish_phabricator_review_workflow/

如果你之前用過(guò)其它的Code Review工具,可能會(huì)對(duì)這樣的流程感到不習(xí)慣。在其它工具中,變更(代碼,資源文件或其它)會(huì)經(jīng)歷這樣一個(gè)流程: Write, Publish, Review, Merge。首先,你做出一些變更(Write),然后把他們推送到遠(yuǎn)程倉(cāng)庫(kù)(Publish)等待審查者審查。一旦這些代碼被審查(Review)并通過(guò),變更會(huì)合并(Merge)到一個(gè)指定的功能分支。在這個(gè)流程中,被合并的變更恰好是被推送的變更(這句話(huà)有點(diǎn)模模糊糊,不痛不癢,接下來(lái)我們看一下Phabricator的流程,也許會(huì)清晰很多)。
接下來(lái),我們看一下Phabricator略有不同的工作流:Write, Review, Merge, Publish。像上面一樣,開(kāi)始的時(shí)候,你做出一些變更。但是,接下來(lái)的流程就不一樣了。
Phabricator認(rèn)為在開(kāi)發(fā)過(guò)程中審查(Review)是一個(gè)重要的步驟,對(duì)于那些沒(méi)有審查過(guò)的變更,是不可以發(fā)布的。
理論上來(lái)說(shuō),沒(méi)有審查過(guò)的變更不算數(shù):這些變更可能只是臨時(shí)的,易變的。可能方法上不對(duì),可能缺少來(lái)龍去脈,可能根本就是解決錯(cuò)誤的問(wèn)題,等等。審查的參考基礎(chǔ)是建立在開(kāi)發(fā)人員和審查人員擁有一個(gè)共同認(rèn)可的變更處理方式,并且這種處理方式是開(kāi)發(fā)過(guò)程所有參與人員(項(xiàng)目管理、產(chǎn)品、開(kāi)發(fā))都期望的,而不僅僅是僅僅做到最終的產(chǎn)品看起來(lái)沒(méi)問(wèn)題。直到變更經(jīng)過(guò)了這樣的審查,我們才能得到穩(wěn)固的版本。
這樣的工作流跟其它工具的審查流程沒(méi)有實(shí)質(zhì)上的技術(shù)區(qū)別,但是存在明顯的社交活動(dòng)上的不同:由于變更必須經(jīng)過(guò)審查才能被合并、發(fā)布,變更作者需要根據(jù)反饋對(duì)變更進(jìn)行調(diào)整。另外,審查者根據(jù)粗略的草圖(所有開(kāi)發(fā)參與人員共同認(rèn)可的變更方式)進(jìn)行反饋,而不是簡(jiǎn)單的批判一件已經(jīng)完成的變更工作。
Phabricator和其它工具的工作流都有著同樣的目的:未審查的代碼都只是臨時(shí)的變更,沒(méi)有長(zhǎng)久或者明顯的價(jià)值,直到通過(guò)審查。
Phabricator工作流的第二步是審查(Review),審查的對(duì)象是還沒(méi)有發(fā)布的變更。沒(méi)有發(fā)布的變更被發(fā)送到Phabricator等待被審查(通常我們使用 arc diff命令發(fā)送審查請(qǐng)求),然后審查者做出反饋。變更作者根據(jù)反饋進(jìn)行修改,在修改過(guò)程中,作者不必?fù)?dān)心版本、解決方式這些事情。作者可以自由的復(fù)位、使用、移除或者舍棄老的變更。在從變更提交審核到審核者反饋,以及作者再次修改整個(gè)過(guò)程中,沒(méi)有那種審核者把作者推入一個(gè)必須接受或者只能做少量改變的默認(rèn)發(fā)布狀態(tài)。
一旦通過(guò)審核,變更會(huì)被合并(Merge)和發(fā)布(Publish)(通常,這兩個(gè)步驟由一個(gè)命令完成 arc land)。
這里,Phabricator也與那些先 Publish 的工具不同:默認(rèn)情況下,Phabricator會(huì)舍棄到達(dá)最后變更前的所做的中間過(guò)程,把最后變更的整個(gè)過(guò)程壓縮成一次提交。總體來(lái)說(shuō),這意味著舍棄checkpoint commits, rebases, squash-merges, 并且把整個(gè)變更過(guò)程做為一次 fast-forward commit 提交到目標(biāo)分支。
Phabricator在一定程度上能做到這些,是因?yàn)椋菏裁炊紱](méi)有被發(fā)布,所以這種工作流可以以任何想要的方式發(fā)布變更。
有了這些,我們可以以我們想要的版本自由的rebase,fast-commit,這些是Phabricator默認(rèn)的行為。

0x62 進(jìn)行Code Review所用工具

做為一般用戶(hù),常用的工具有兩個(gè) DifferentialArcanist

  • Differential-審查代碼的工作臺(tái)

我們?cè)谶@里查看變更審查情況,對(duì)變更進(jìn)行審查或評(píng)論等操作。
這是某次變更界面操作部分截圖

<p>做為 審查人,可進(jìn)行的操作有:
Comment:說(shuō)點(diǎn)什么。可以針對(duì)某行代碼進(jìn)行評(píng)論,直接點(diǎn)擊行號(hào)即可
Accept Revision:接受變更,這哥們代碼寫(xiě)得不錯(cuò),不需要改
Request Changes:不行,還要改
Resign as Reviewer:重新指定審查代碼的人
Commandeer Revision:字面意思是將這個(gè)Revision據(jù)為己有的意思,實(shí)際上這個(gè)時(shí)候Reviewer的身份已經(jīng)變?yōu)镺wner的身份了,不能再進(jìn)行Review了,但是Comment還是可以的
Add Reviewer:添加審查人
Add Subscribers:添加訂閱者,CC

做為 作者,可進(jìn)行的操作有:
Comment:說(shuō)點(diǎn)什么。可以針對(duì)某行代碼進(jìn)行評(píng)論,直接點(diǎn)擊行號(hào)即可
Abandon Revision:廢除版本。廢除后,這個(gè)版本就不需要再審核了
Plan Changes:計(jì)劃變更,我自己發(fā)現(xiàn)了一些問(wèn)題或者需求有變,正在改
Add Reviewer:添加其它審查人(除當(dāng)前審查人外)
Add Subscribers:添加訂閱者,CC

  • Arcanist - 命令交互
    我們用這個(gè)工具提交變更和審查請(qǐng)求,對(duì)變更做出更改,或者在通過(guò)審查后發(fā)布到遠(yuǎn)程倉(cāng)庫(kù)分支中。
    常用的命令有:
    arc diff:發(fā)送變更詳情和審查請(qǐng)求
    arc land:推送變更(Git and Mercurial),當(dāng)通過(guò)審查后使用這個(gè)命令
    arc list:顯示變更處理的情況
    arc cover:查找最有可能審查變更的人
    arc patch:給版本打補(bǔ)丁
    arc export:從Differential下載補(bǔ)丁
    arc amend:更新Git commit
    arc commit:提交變更(SVN)
    arc branch:查看Git branches更加詳細(xì)的信息

在配置了 lint 和 unit test intergration后,可以用這些命令:
arc lint:靜態(tài)代碼檢查
arc unit:?jiǎn)卧獪y(cè)試

與其它工具交互:
arc upload:上傳文件
arc download:下載文件
arc paste:創(chuàng)建和查看剪貼

還有一些高級(jí)功能:
arc call-conduit:執(zhí)行 Conduit 方法
arc liberate:創(chuàng)建或更新 libphutil 庫(kù)
arc shell-complete:激活 tab 補(bǔ)全

0x63 配置進(jìn)行Code Review

一些基本的配置和安裝 ---> 寫(xiě)代碼 ---> 提交審查請(qǐng)求(arc diff) ---> 審查(Differential) ---> (審查通過(guò)后)合并提交(arc land)

  • 一些基本的配置和安裝
    包括:
    配置代碼倉(cāng)庫(kù)(Diffusion)
    把你本地的Git遠(yuǎn)程URL設(shè)置為Phabricator上代碼倉(cāng)庫(kù)地址
    安裝Arcanist
    配置Project信息

  • 配置代碼倉(cāng)庫(kù)(Diffusion)
    在開(kāi)始進(jìn)行代碼審查后,我們的代碼是由Phabricator直接托管的,所以我們需要配置代碼倉(cāng)庫(kù)。
    使用管理員賬號(hào)登錄Phabricator,點(diǎn)擊左側(cè)面板菜單 Diffusion ,然后點(diǎn)擊右上側(cè) Create Repository ,選擇你所使用的 Repository 類(lèi)型,填寫(xiě) Name 等信息,在創(chuàng)建完成后即可使用。如果沒(méi)有什么特殊的需求,不需要進(jìn)行特別的配置,這里列舉兩種你可能遇到的打算開(kāi)始使用 Phabricator 時(shí)的場(chǎng)景:

1、代碼之前由 GitHub 或其它托管,現(xiàn)在我需要把之前的代碼導(dǎo)入
點(diǎn)擊 Manage Repository ,點(diǎn)擊左側(cè) URIs,點(diǎn)擊 Add New URI,填寫(xiě)GitHub或其它托管系統(tǒng)對(duì)應(yīng)倉(cāng)庫(kù)的 URI , I/O Type 選擇 Observe,點(diǎn)擊 Create Repository URI 添加新的 URI 。


在添加完新的 URI 后,你還需要點(diǎn)擊 Set Credential 設(shè)置訪(fǎng)問(wèn)新的 URI 的認(rèn)證方式。
如果你打算此時(shí)就開(kāi)始使用 Phabricator ,請(qǐng)務(wù)必通知你的團(tuán)隊(duì),暫停一下,不要再向GitHub等提交代碼。如果你的 GitHub 等也設(shè)置了代碼審查,請(qǐng)督促相關(guān)人員完成代碼審查流程。
稍等片刻,待 Phabricator 同步完之前的代碼后,編輯你添加的 GitHub 或其它代碼托管系統(tǒng)的 URI ,務(wù)必修改 I/O Type
1)如果你不再需要使用之前的托管系統(tǒng),選擇 No I/O
2)如果你想繼續(xù)把代碼備份到之前的代碼托管系統(tǒng),選擇 Mirror,這時(shí), Phabricator 代碼倉(cāng)庫(kù)的變更會(huì)覆蓋推送到之前的代碼托管系統(tǒng)
如果你不修改 I/O Type,向 Phabricator 代碼倉(cāng)庫(kù)提交代碼會(huì)失敗,因?yàn)槭侵蛔x的。
當(dāng)然,對(duì)于導(dǎo)入之前的代碼,還有別的方式,例如直接把本地的代碼再次向 Phabricator 代碼倉(cāng)庫(kù)再提交一次。

2、開(kāi)始一個(gè)新的項(xiàng)目,創(chuàng)建一個(gè)新的倉(cāng)庫(kù)
參考第1種場(chǎng)景,在 Phabricator 創(chuàng)建代碼倉(cāng)庫(kù)。如果你希望把代碼備份到其它的托管系統(tǒng),只需要添加對(duì)應(yīng)的 URI,并且把 I/O Type 選為 Mirror

  • 把你本地的Git遠(yuǎn)程URL設(shè)置為Phabricator上代碼倉(cāng)庫(kù)地址
git remote set-url 遠(yuǎn)程名稱(chēng) 新的url
  • 安裝Arcanist

https://secure.phabricator.com/book/phabricator/article/arcanist_quick_start/

  • 配置Project信息
    在你項(xiàng)目代碼的根目錄下,創(chuàng)建 .arcconfig 文件,內(nèi)容如下:
{
  "phabricator.uri" : "你Phabricator系統(tǒng)訪(fǎng)問(wèn)URL"
}

Windows系統(tǒng)下,創(chuàng)建類(lèi)似這種文件名的文件可能很麻煩,可以使用這條命令創(chuàng)建:

arc set-config phabricator.uri "你Phabricator系統(tǒng)訪(fǎng)問(wèn)URL"

Windows系統(tǒng)下,還需要配置 Editor ,詳情參考:

https://secure.phabricator.com/book/phabricator/article/arcanist_windows/

Arcanist 使用可參考:

https://secure.phabricator.com/book/phabricator/article/arcanist_quick_start/
https://secure.phabricator.com/book/phabricator/article/arcanist/

在進(jìn)行完基本的配置和安裝后,可以開(kāi)始 Code Review 了。

  • 寫(xiě)代碼
    當(dāng)然,不只是代碼可以被審查,圖標(biāo)等資源文件的變更也可以被審查。

  • 提交審查請(qǐng)求(arc diff)
    一般情況下,我們直接使用 arc diff 即可,默認(rèn)情況下,Arcanist 會(huì)把本地分支的 HEAD 與遠(yuǎn)程對(duì)應(yīng)分支的 HEAD 進(jìn)行對(duì)比,并生成差異對(duì)比發(fā)送到 Phabricator。當(dāng)你所做的修改沒(méi)有 commit 時(shí),會(huì)提示你進(jìn)行 commit。
    在一些情況下,我們并不希望與本地分支的 HEAD 進(jìn)行比較,假設(shè)想要與上次的 commit 比較,上次 commit id 是 8ffc88dc05d31fffd28e3ff1129d1b8c321dffff,那么我們需要在 arc diff 后把這個(gè) id 加上:arc diff 8ffc88dc05d31fffd28e3ff1129d1b8c321dffff
    執(zhí)行這條命令時(shí)我們需要按照模板填寫(xiě)title(必填),summary(必填),Test Plan(必填,沒(méi)有可寫(xiě) N/A 之類(lèi)的標(biāo)識(shí)),Reviewers(必填,且必須為真實(shí)有效的用戶(hù)名),Subscribers(可選),填寫(xiě)完成后關(guān)閉編輯器,Arcanist會(huì)自動(dòng)提交審查請(qǐng)求。

  • 審查(Differential)
    做為 審查人,需要在 Differential 工作臺(tái)完成代碼審查工作,上面已經(jīng)介紹了 Differential,這里就不再多說(shuō)了。

  • (審查通過(guò)后)合并提交(arc land)
    做為 作者,在代碼審查通過(guò)后,需要使用 arc land 把變更發(fā)布到遠(yuǎn)程分支。
    注意,在首次執(zhí)行這條命令前(不一定非要到這個(gè)步驟,可以是這個(gè)步驟前的任意時(shí)刻,例如開(kāi)始寫(xiě)代碼前),建議請(qǐng)使用 git branch -u 遠(yuǎn)程名稱(chēng)/遠(yuǎn)程分支名稱(chēng) 把本地的分支與遠(yuǎn)程分支相關(guān)聯(lián),否則,在執(zhí)行完 arc land 后,本地分支會(huì)被刪除。如果你不想這樣做,又需要保留現(xiàn)在分支的話(huà),請(qǐng)使用 arc land --keep-branch
    默認(rèn)情況下,Arcanist 會(huì)把變更推送到與本地分支相關(guān)聯(lián)的遠(yuǎn)程分支,你可以使用 * --remote * 和 * --onto * 參數(shù)推送到你想要的遠(yuǎn)程和遠(yuǎn)程分支。
    關(guān)于 arc land 的詳細(xì)說(shuō)明,可使用 arc land --help 查看。

0x70 與GitHub集成

這里的“集成”其實(shí)說(shuō)的很心虛,因?yàn)樵谑褂?Phabricator 后,GitHub 已經(jīng)變?yōu)橐粋€(gè)文件存儲(chǔ)服務(wù)器了。常見(jiàn)的使用情況已經(jīng)在 ** 0x63 配置進(jìn)行Code Review ** 的 ** 配置代碼倉(cāng)庫(kù)(Diffusion)** 中寫(xiě)出,所以你懂的。

0x80 與Jenkins集成

在很久很久以前,我已經(jīng)搭建了 Jenkins 用于自動(dòng)構(gòu)建,所以這次把 Phabricator 與 Jenkins 做了集成。
在 Jenkins 中安裝完插件:* Phabricator Differential Plugin * 后,請(qǐng)參考這篇文章:

https://github.com/uber/phabricator-jenkins-plugin#phabricator-jenkins-plugin--

0x90 結(jié)束語(yǔ)

從配置完到開(kāi)始試用已經(jīng)有一個(gè)月左右,期間遇到了各種問(wèn)題。經(jīng)歷了這些問(wèn)題的洗禮,算是對(duì) Phabricator 使用入門(mén)了吧。
這篇文章時(shí)隔多日才完成,盡管我想把每個(gè)細(xì)節(jié)寫(xiě)的詳盡,但是記憶總是像被蟲(chóng)蛀過(guò)的木頭,難免有些疏漏。加之文筆水平有限,各位就湊合著看吧。
在安裝和使用過(guò)程中遇到的問(wèn)題,歡迎各位評(píng)論交流。

0xA0 Q/A

1、如何強(qiáng)制用戶(hù) Code Review?
再次強(qiáng)調(diào)一下前提:在開(kāi)始 Code Review 流程前,請(qǐng)先確認(rèn)團(tuán)隊(duì)成員的git remote url已經(jīng)切換為Phabricator上對(duì)應(yīng)倉(cāng)庫(kù)地址。
強(qiáng)制用戶(hù)Code Review,需要?jiǎng)?chuàng)建Herald Rule。在創(chuàng)建時(shí),New Rule for 選:Commit Hook: Commit Content.Rule Type選:Global,或者根據(jù)自己需要選擇;Conditions中是組合條件,可以根據(jù)自己需要指定一些條件;Action 指定當(dāng)前情況符合你指定的條件組合時(shí)執(zhí)行的動(dòng)作。示例如圖:

示例中定義了以下規(guī)則:在向develop分支提交代碼時(shí),所提交的代碼必須是通過(guò) Code Review 流程審查通過(guò)的,否則會(huì)被拒絕;除非 Commit Message 中包含字符 @bypass-review 。
指定 Commit Message 中包含字符 @bypass-review 這種例外情況,主要考慮到在緊急修復(fù)一些問(wèn)題,沒(méi)時(shí)間等待審查時(shí)使用。
當(dāng)提交被拒絕時(shí),如圖:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,786評(píng)論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,656評(píng)論 3 419
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 176,697評(píng)論 0 379
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 63,098評(píng)論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,855評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,254評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,322評(píng)論 3 442
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,473評(píng)論 0 289
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,014評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,833評(píng)論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,016評(píng)論 1 371
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,568評(píng)論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,273評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,680評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,946評(píng)論 1 288
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,730評(píng)論 3 393
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,006評(píng)論 2 374

推薦閱讀更多精彩內(nèi)容