Reviewbot 開源 | 為什麼我們要打造自己的程式碼審查服務?

Changjun Ji發表於2024-11-07

Reviewbot 是七牛雲開源的一個專案,旨在提供一個自託管的程式碼審查服務, 方便做 code review/靜態檢查, 以及自定義工程規範的落地。


靜態檢查不是個新鮮事。

我記得早在幾年前,我們就調研並使用過 sonarqube 做靜態檢查,但當時並沒有大範圍的推廣。主要原因在於,一是發現的問題多數是風格問題,較少能發現缺陷; 二是 sonarqube 社群版的 worker 數有限制,滿足不了我們大規模程式碼掃描的需求。當然,也是因為前一個問題,感覺付費並不是很划算。

而由於七牛主要使用 golang 語言,所以在靜態檢查方面,我們基本使用 go vet/fmt/lint 等,再就是後來的 golangci-lint,好像也夠用了。

但隨著程式碼倉庫的增多,以及對工程規範的不斷強化,我們越來越發現當前的落地方式,已經開始無法滿足我們的需求。

Linter 工具的引入與更新問題

以 golangci-lint 為例,它是 go 語言 linters 聚合器,內建了 100+ linters,使用也很簡單, golangci-lint run 一條命令即可。但你知道嗎?如果沒有特殊配置,你這條命令其實僅僅執行其中的 6 個 linter,絕大部分 linters 都沒有執行!

另外,工具本身需要更新,且很多時候我們也會自己定製 linter 工具,這種時候該怎麼做呢?如果僅有少量倉庫,可能還好,但如果倉庫很多,那維護成本就上去了。

還有就是新業務,新倉庫,如何保證相關的檢查能夠及時配置,相關的規範能夠正確落地?

靠自覺一定是不行的。

Linter 問題的發現與修復情況

如何確保發現的問題能夠被及時修復?如何讓問題能更及時、更容易的被修復?

埋藏在大量 raw log 中的問題,一定是不容易被發現的,查詢起來很麻煩,體驗很差。

歷史程式碼倉庫的存量問題,誰來改?改動就需要時間,但實際上很多業務研發可能並沒有動力來跟進。同樣,變動總是有風險的,有些 lint 問題修復起來也並不簡單,如果因修復 lint 問題而引入風險,那就得不償失了。

如果想了解當前組織內 lint 問題的分佈及修復情況,又該怎麼辦呢?

如何解決,方向在哪裡?

不可否認,linter 問題也是問題,如果每行程式碼都能進行充分的 lint 檢查,那一定比不檢查要強。

另一方面,組織內製定好的工程規範,落地在日常的開發流程中,那一定是希望被遵守的,這類就是強需。

所以這個事情值得做,但做的方式是值得思考的,尤其是當我們有更高追求時。

參考 CodeCov 的服務方式,以及 golangci-lint reviewdog 等工具的設計理念,我們認為:

  • 如果能對於新增倉庫、歷史倉庫,不需要專人配置 job,就能自動生效,那一定是優雅的
  • 如果能只針對 PR/MR 中的變動做分析和反饋,類似我們做 Code Review 那樣,那對於提 PR 的同學來講一定是優雅的,可接受的,隨手修復的可能性極大
    • 而進一步,針對 PR/MR 中涉及的檔案中的歷史程式碼進行反饋,在合理推動下,支援夾帶修改,持續改進的可能性也會大大增強
  • Lint 工具多種多樣,或者我們自己開發出新工具時,能夠較為輕鬆的讓所有倉庫都自動生效,那也一定是非常讚的,不然就可能陷入工具越多負擔越重的風險

基於上面的思考,我認為我們需要的是: 一箇中心化的 Code Review/靜態檢查服務,它能自動接受整個組織內 PR/MR 事件,然後執行各種預定義的檢查,並給與精確到變動程式碼行的有效反饋。它要能作為程式碼門禁,持續的保障入庫程式碼質量。

Reviewbot 就是這樣一個專案。

Reviewbot 在設計和實現上有哪些特點?

面向改進的反饋方式

這將是 Reviewbot 反饋問題的核心方式,它會盡可能充分利用各 Git 平臺的自身能力,精確到變動的程式碼行,提供最佳的反饋體驗。

  • Github Check Run (Annotations)

  • Github Pull Request Review (Comments)

支援多種 Runner

Reviewbot 是自託管的服務,推薦大家在企業內自行部署,這樣對私有程式碼更友好。

Reviewbot 自身更像個管理服務,不限制部署方式。而對於任務的執行,它支援多種 Runner,以滿足不同的需求。比如:

  • 不同的倉庫和 linter 工具,可能需要不同的基礎環境,這時候你就可以將相關的環境做成 docker 映象,直接透過 docker 來執行
  • 而當任務較多時,為了執行效率,也可以選擇透過 kubernetes 叢集來執行任務。

使用也很簡單,在配置檔案中的目標倉庫指定即可。類似:

dockerAsRunner:
  image: "aslan-spock-register.qiniu.io/reviewbot/base:go1.22.3-gocilint.1.59.1"
kubernetesAsRunner:
  image: "aslan-spock-register.qiniu.io/reviewbot/base:go1.23.2-gocilint.1.61.0"
  namespace: "reviewbot"

零配置 + 定製化

本質上,Reviewbot 也是個 webhook 服務,所以我們只需要在 git provider 平臺配置好 Reviewbot 的回撥地址即可 (github 也可以是 Github App)。

絕大部分的 linter 的預設最佳執行姿勢都已經固定到程式碼中,如無特殊,不需要額外配置就能對所有倉庫生效。

而如果倉庫需要特殊對待,那就可以透過配置來調整。

類似:

org/repo:
  linters:
    golangci-lint:
      enable: true
      dockerAsRunner:
        image: "aslan-spock-register.qiniu.io/reviewbot/base:go1.22.3-gocilint.1.59.1"
      command:
        - "/bin/sh"
        - "-c"
        - "--"
      args:
        - |
          source env.sh
          export GO111MODULE=auto
          go mod tidy
          golangci-lint run --timeout=10m0s --allow-parallel-runners=true --print-issued-lines=false --out-format=line-number >> $ARTIFACT/lint.log 2>&1

可觀察

Reviewbot 是在對工程規範強管理的背景下產生的,那作為工程規範的推動方,我們自然有需求想了解組織內當前規範的執行情況。比如, 都有哪些問題被檢出?哪些倉庫的問題最多?哪些倉庫需要特殊配置?

目前 Reviewbot 支援透過企業微信來接收通知,比如:

  • 檢出有效問題

  • 遇到錯誤

當然,未來可能也會支援更多方式。

其他更多的功能和姿勢,請參考倉庫: https://github.com/qiniu/reviewbot

Reviewbot 的未來規劃

作為開源專案,Reviewbot 還需要解決很多可用性和易用性問題,以提升使用者體驗,比如最典型的,接入更多的 git provider(gitlab/gitee 等),支援 CLI 模式執行。

但我個人認為,作為 code review 服務,提供更多的檢測能力,才是重中之重。因為這不光是行業需求,也是我們自身需要。

所以後面我們除了會引入七牛內部推薦的規範,也會調研和探索更多的行業工具,同時會考慮引入 AI,探索 AI 在 code review 中的應用等等。

Anyway,Reviewbot 還很年輕,我們在持續的改進中,非常歡迎大家試用並提出寶貴意見。當然,更歡迎大家一起參與到專案建設中來。

感謝大家。

相關文章