本文最初發佈於Mozilla Hacks,由InfoQ中文站翻譯並分享。
多年以來,Mozilla的工程團隊不斷爲(提高)代碼質量而引入工具。這一套工具鏈可以在Firefox複雜開發週期的不同階段發揮作用。在本文,我們將介紹我們使用的開發工具類型、工具解決的一些挑戰和我們設計的架構解決方案。當我們談到代碼質量工具時,主要指以下幾類工具:
- 靜態分析
- 代碼檢查
- 代碼分析
- 代碼覆蓋度
一般而言,對於比構建Firefox桌面瀏覽器更小的開發項目,簡易CI(持續集成)作業的設置和配置相對比較容易。它們的目標語言數量有限。開發人員有許多設置和CI平臺可以使用。
而Firefox是一個龐大的開源軟件項目,它有2100萬行代碼,由網景公司在1998年創建。我們使用C++、Rust、JavaScript、Python等多種語言,每天處理數百個更改,並且與有好幾個GB的大型存儲庫打交道。這帶來一些獨特的挑戰!
使用的工具
我們使用的一些工具:
同時,我們將重點聚焦這些使用工具的原因和方式。關於所有這些工具的更多細節,你可以查看文檔。由於很難在Firefox開發人員的工作站上使用這些工具,我們決定在審查階段集中精力運行這些工具。
面臨的挑戰
不同的失敗類型
當測試(代碼)質量時,我們會遇到不同類型的失敗。這是我們面臨的第一個挑戰:
-
部分issues需要中斷CI(持續集成),沒有假陽性(構建錯誤、未嚴格遵守某些強制性格式化規則等)。例如,我們有針對特定代碼庫的自定義C++檢查器。我們知道它們會給產品帶來問題。因此,我們要確保中斷CI,以防止代碼在產品中落地並造成麻煩。
-
潛在錯誤:根據不同的觀點,C/C++要麼太複雜,要麼就是容易產生問題的語言。因此,我們開發了一些工具(靜態分析器)來避免問題產生。然而,這些檢查器存在假陽性報告。(否則,它們會成爲編譯器觸發的錯誤。)
例如,clang-tidy“有損於性能的參數值”
-
能有最好的工具:可以增強代碼庫一致性的檢查器,讓代碼更具可讀性,並減少技術債務。
代碼庫的規模
下一個主要挑戰是:我們要與2100萬行代碼打交道。在啓用新檢查器前,我們無法完全修復現有的數百個問題,並且我們也不想強迫開發人員修復所有與他們建議更改的無關問題。所以,在這種規模下,我們必須想出不同的解決方案。
爲解決這個問題,我們已經確定並部署了兩個解決方案。當issues容易修復時(例如eslint、flake8等),我們創建並維護一個它們可以在上面運行的目錄/文件列表,並按目錄逐個修復問題。
對於更復雜的檢查器,比如C++靜態分析器,我們想出一些啓發式方法來識別問題是新是舊。我們要麼創建一個以前接受的用法列表(例如:已廢棄的線程使用方法),要麼使用一些啓發式方法來評估缺陷是新的還是舊的。
架構
我們目前最大的優勢在於,使用的工具是由Mozilla優秀的工程團隊構建的。我們用內部的CI系統 Taskcluster來測試和構建Firefox。此外,在發佈前,我們還會使用自己的Phabricator實例來檢查Firefox的每個補丁。
工作流
每個補丁都遵循同樣的工作流:
- Phabricator通知我們的Web服務有新補丁需要分析;
- Web服務會使用一個工作進程池將補丁及之前的版本應用到預先克隆好的存儲庫上。(還記得吧,Firefox的主存儲庫有幾GB。)
- 之後,該補丁會被推送到我們的Try服務器。該服務器是一個Mercurial服務器,Mozilla開發人員會用它觸發CI構建(來嘗試構建)。
- Try服務器在Taskcluster上創建一組代碼分析任務。這些任務和它們的觸發規則是由開發人員在Firefox的源代碼中定義的。
- 每個代碼分析任務都會生成一個JSON負載,列出從棧中找到的所有潛在缺陷。
- 最後,發佈任務分析、聚合和過濾所有問題。然後,它在Phabricator和我們的Web服務中發佈相關內容。這樣,開發人員就可以在任何時候查看它們,並在出現問題時收到通知。
對於大多數補丁,這個工作流通常執行要花費12到15分鐘。一些修改文件非常多的補丁可能會觸發更多的分析程序,處理起來也會更慢。
關於架構的更多信息,請查看項目文檔。
優點
這種方法的主要優點在於它讓我們可以利用許多現有工具,而且這些工具也能在開發人員自己的計算機上使用。(這可以通過mach工具實現)。
另一個很大的好處是:我們無需維護自己的分析程序,也不需要維護它們的依賴關係。這些分析器可以保證一直運行最新的版本,因爲它們是在Firefox代碼庫中定義的,並由全球各地的人維護。
目前,我們支持特定的分析程序(clang-tidy、clang-format、rustfmt、mozlint等)以及通用格式。這讓任何Firefox開發人員都可以輕鬆地擴展我們平臺的功能。
它看上去是什麼樣子?
以下是Phabricator上的一些issues截圖。這些是大多數Mozilla Firefox開發人員都可以看到的工作流視圖。
在修訂中發現的所有issues:
彙總說明清單:
補丁自身報告的issues:
未來計劃
這個關於代碼質量的工作流項目是由一個小團隊在過去幾年構建的。在去年,它已經處於一個非常好的穩定性水平。現在,對來自Firefox開發人員的每個補丁,我們平均用不到15分鐘就可以處理完。
並且,我們還通過這個平臺支持其他幾個Mozilla項目:NSS (Firefox中的主要加密庫)、一些CI內部項目,預計將來還會有其他新項目。
幾個月來,我們一直在與Ubisoft合作進行一項實驗,用機器學習來分析審查階段的補丁。該分析會提交一份詳細報告,評估補丁風險,這取決於很多因素(例如複雜性、過程度量等等)。將來,這個項目或許可以幫助我們減少Firefox代碼庫中的迴歸數量,並提高審查速度。
在接下來的幾個季度中,我們的目標是通過將Mozilla fuzzers移植到Taskcluster在落地階段引入模糊測試(fuzzing)。我們還希望在不向開發人員發送垃圾郵件的情況下報告更多問題,採用一些方法來避免重複,包括僅報告修訂更新時可能是新問題的問題、列出補丁帶來的問題,或者與以前已知的狀態進行比較。
最後,我們希望利用工程流程團隊開發的新電子郵件通知系統來增強我們的報告系統。這可能會改進問題在Phabricator中的顯示方式,並擴展我們對檢測到的問題進行說明和分析的能力。
打上補丁。我們希望Firefox的每一個新版本都能帶來這樣的變化。另一方面,我們爲我們開發的代碼質量工具感到驕傲,這些工具可以支持Mozilla工程師和貢獻者構建更好的Firefox。
如果你想參與或者瞭解更多關於Firefox構建的知識,這有很多方法可以讓你參與到瀏覽器技術的構建中。代碼審查平臺已經開源,你可以從Github上獲得。
英文原文:
Engineering code quality in the Firefox browser: A look at our tools and challenges