Gerrit代碼審覈服務器的工作流程和原理

Gerrit 代碼審覈服務器的工作流和原理

谷歌 Android 開源項目在 Git 的使用上有兩個重要的創新,一個是爲多版本庫協同而引入的 repo,這在之前我們已經詳細討論過。另外一個重要的創新就是 Gerrit —— 代碼審覈服務器。Gerrit 爲 Git 引入的代碼審覈是強制性的,就是說除非特別的授權設置,向 Git 版本庫的推送(Push)必須要經過 Gerrit 服務器,修訂必須經過代碼審覈的一套工作流之後,纔可能經批准並納入正式代碼庫中...

6.7   Gerrit 代碼審覈服務器

首先貢獻者的代碼通過 git 命令(或 repo 封裝)推送到 Gerrit 管理下的 Git 版本庫,推送的提交轉化爲一個一個的代碼審覈任務,審覈任務可以通過 refs/changes/<change-id> 下的引用訪問到。代碼審覈者可以通過 Web 界面查看審覈任務、代碼變更,通過 Web 界面做出通過代碼審覈或者打回等決定。測試者也可以通過 refs/changes/<change-id> 引用獲取(fetch)修訂對其進行測試,如果測試通過就可以將該評審任務設置爲校驗通過(verified)。最後經過了審覈和校驗的修訂可以通過 Gerrit 界面中提交動作合併到版本庫對應的分支中。 在 Android 項目的網站的代碼貢獻流程圖更爲詳細的介紹了 Gerrit 代碼審覈服務器的工作流程。 

代碼審覈工作流

6.7.1   Gerrit 的實現原理

SSH 協議的 Git 服務器 Gerrit 本身基於 SSH 協議實現了一套 Git 服務器,這樣就可以對 Git 數據推送進行更爲精確的控制,爲強制審覈的實現建立了基礎。 Gerrit 提供的 Git 服務的端口並非標準的 22 端口,缺省是 29418 端口。可以訪問 Gerrit 的 Web 界面得到這個端口。對 Android 項目的代碼審覈服務器,訪問https://review.source.android.com/ssh_info 就可以查看到 Git 服務的服務器域名和開放的端口。下面我們用 curl 命令查看網頁的輸出。
$ curl -L -k http://review.source.android.com/ssh_info
review.source.android.com 29418
特殊引用 refs/for/<branch-name> 和 refs/changes/nn/<task-id>/m Gerrit 的 Git 服務器,禁止用戶向 refs/heads命名空間下的引用執行推送(除非特別的授權),即不允許用戶直接向分支進行提交。爲了開發者能夠向 Git 服務器提交修訂,Gerrit 的 Git 服務器只允許用戶向特殊的引用 refs/for/<branch-name> 下執行推送,其中 <branch-name> 即爲開發者的工作分支。向 refs/for/<branch-name> 命名空間下推送並不會在其中創建引用,而是爲新的提交分配一個 ID,稱爲 task-id ,併爲該 task-id 的訪問建立如下格式的引用 refs/changes/nn/<task-id>/m ,其中:
  • task-id 爲 Gerrit 爲評審任務順序分配的全局唯一的號碼。
  • nn 爲 task-id 的後兩位數,位數不足用零補齊。即 nn 爲 task-id 除以 100 的餘數。
  • m 爲修訂號,該 task-id 的首次提交修訂號爲 1,如果該修訂被打回,重新提交修訂號會自增。
Git 庫的鉤子腳本 hooks/commit-msg 爲了保證已經提交審覈的修訂通過審覈入庫後,被別的分支 cherry-pick 後再推送至服務器時不會產生新的重複的評審任務,Gerrit 設計了一套方法,即要求每個提交包含唯一的 Change-Id,這個 Change-Id 因爲出現在日誌中,當執行 cherry-pick 時也會保持,Gerrit 一旦發現新的提交包含了已經處理過的 Change-Id ,就不再爲該修訂創建新的評審任務和 task-id,而直接將提交入庫。 爲了實現 Git 提交中包含唯一的 Change-Id,Gerrit 提供了一個鉤子腳本,放在開發者本地 Git 庫中(hooks/commit-msg)。這個鉤子腳本在用戶提交時自動在提交說明中創建以 "Change-Id: " 及包含 git hash-object 命令產生的哈希值的唯一標識。當 Gerrit 獲取到用戶向refs/for/<branch-name> 推送的提交中包含 "Change-Id: I..." 的變更 ID,如果該 Change-Id 之前沒有見過,會創建一個新的評審任務並分配新的 task-id,並在 Gerrit 的數據庫中保存 Change-Id 和 Task-Id 的關聯。 如果當用戶的提交因爲某種原因被要求打回重做,開發者修改之後重新推送到 Gerrit 時就要注意在提交說明中使用相同的 “Change-Id” (使用 --amend 提交即可保持提交說明),以免創建新的評審任務,還要在推送時將當前分支推送到 refs/changes/nn/task-id/m中。其中 nn 和 task-id 和之前提交的評審任務的修訂相同,m 則要人工選擇一個新的修訂號。 以上說起來很複雜,但是在實際操作中只要使用 repo 這一工具,就相對容易多了。 其餘一切交給 Web Gerrit 另外一個重要的組件就是 Web 服務器,通過 Web 服務器實現對整個評審工作流的控制。關於 Gerrit 工作流,參見在本章開頭出現的 Gerrit 工作流程圖。 感受一下 Gerrit 的魅力?直接訪問 Android 項目的 Gerrit 網站: https://review.source.android.com/ 。
Android 項目代碼審覈網站
Android 項目的評審網站,匿名即可訪問。點擊菜單中的 “Merged” 顯示了已經通過評審合併到代碼庫中的審覈任務。下面的一個界面就是 Andorid 一個已經合併到代碼庫中的歷史評審任務。

Android 項目的 16993 號評審

在該界面我們可以看到:
  • URL 中顯示的評審任務編號爲 16993。
  • 該評審任務的 Change-Id 以字母 I 開頭,包含了一個唯一的 40 位 SHA1 哈希。
  • 整個評審任務有三個人蔘與,一個人進行了檢查(verify),兩個人進行了代碼審覈。
  • 該評審任務的狀態爲已合併:“merged”。
  • 該評審任務總共包含兩個補丁集: Patch set 1 和 Patch set 2。
  • 補丁集的下載方法是: repo download platform/sdk 16993/2 。
如果使用 repo 命令獲取補丁集是非常方便的,因爲封裝後的 repo 屏蔽掉了 Gerrit 的一些實現細節,例如補丁集在 Git 庫中的存在位置。如前所述,補丁集實際保存在 `refs/changes` 命名空間下。使用 `git ls-remote` 命令,從 Gerrit 維護的代碼庫中我們可以看到補丁集對應的引用名稱。
$ git ls-remote ssh://review.source.android.com:29418/platform/sdk refs/changes/93/16993*
5fb1e79b01166f5192f11c5f509cf51f06ab023d        refs/changes/93/16993/1
d342ef5b41f07c0202bc26e2bfff745b7c86d5a7        refs/changes/93/16993/2
接下來我們就來介紹一下 Gerrit 服務器的部署和使用方法。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章