RFC-0095 - 從樹狀結構外建構及組合工作站

RFC-0095:建構及組合工作站的樹狀結構外
狀態已接受
區域
  • 一般
說明

建立工作流程,讓使用者在 fuchsia.git 以外建構及組合 Workstation 產品。

Gerrit 變更
作者
審查人員
提交日期 (年-月-日)2021-03-24
審查日期 (年-月-日)2021-05-19

摘要

注意:這項 RFC 已由 RFC-0220 取代,後者已淘汰工作站產品。我們會保留這份 RFC 供後代參考,但不會再推動實作。

工作站產品 (定義為 workstation_session、ermine、終端機和簡易瀏覽器) 目前是在 Fuchsia 來源樹狀結構中建構及組合。Fuchsia 平台和工作站產品之間沒有明確的差異。這項要求是指平台和產品必須同時建構,才能組合成最終產品。我們建議中斷這項耦合,讓工作站元件可與平台分開建構,並在 Fuchsia 來源樹狀結構外組合最終產品。此提案並未說明如何從 Fuchsia 來源樹狀結構中移除工作站產品的實作項目,而是著重於樹狀結構外產品設定和組合的問題。這項工作將奠定基礎,最終可讓 Workstation 產品完全樹狀結構外,但這超出本文的範圍。

請務必注意,終端機被視為 Workstation 產品的基本元件,但 Workstation 產品以外的其他產品也會使用終端機。因此,終端機元件的開發作業將保留在 fuchsia.git 中,並由 Workstation 用作平台的一部分,直到我們就此元件的未來做出進一步決定為止。

提振精神

目前無法在 Fuchsia 上建構及組合產品,同時不建構整個 Fuchsia 平台。我們可以使用 SDK 在 fuchsia.git 外部建構個別元件,但這些構件必須流回 Fuchsia Global Integration,才能組合成最終產品。我們希望能夠提供穩定版平台,讓產品在建構時不必存取 Fuchsia Global Integration。

在建構樹狀結構外產品時,仍有許多未知數,因此我們想先從 Workstation 產品著手。Workstation 產品並非面向使用者的正式產品,而是開發人員參考的資料,以及可讓使用者及早採用平台功能和進行測試的環境,因此這個階段對速度變慢的容忍度較高。Workstation 產品也旨在提供愛好者探索 Fuchsia 的環境。由於不需要建構整個平台,開發人員就能更輕鬆地玩轉 Fuchsia。

設計

獨立映像檔組合工具 RFC-0072 之上,將 Workstation 移至樹狀結構外建構,此提案假設這項工具已存在。

存放區

Workstation 存放區的原始碼會託管在 git-on-borg 上。將程式碼代管在 git-on-borg 上,我們就能使用現有的 Fuchsia 基礎架構和工具,專注於建構及組合產品的任務。

在本文件的其餘部分中,workstation.git 將是指代為 Workstation 產品代管程式碼的存放區。

基礎設施

這個專案的重點是建構及組合樹狀結構外的 Workstation 產品,因此在我們找到方法之前,我們不會將元件的開發工作移出 fuchsia.git。由於元件開發作業會保留樹狀結構內,我們可以依賴現有的測試和建構基礎架構,驗證 Workstation 產品不會發生回歸現象。我們會透過指令碼手動執行平台、SDK、experiences.git 和其他依附元件的新版本推送程序,讓團隊專注於手邊的問題。當我們開始將元件的開發作業轉移至樹狀結構外時,就需要重新檢視如何進行持續整合。

平台的每日版本必須自動化,但我們可以使用現有的 Fuchsia 基礎架構。您需要建立每日建構工具,用於建構組合 Workstation 產品所需的套件,並將這些構件上傳至某些儲存庫。這項工作流程的技術設計仍需進一步釐清。我們會先諮詢基礎架構和安全性團隊,再開始著手處理。

建構 Workstation 產品 (而非核心) 可確保我們擁有產品組合所需的所有構件,即使我們目前未建構這些構件也一樣。我們在樹狀結構外建構的構件會取代平台推出的構件。這樣一來,我們也能使用現有的 Workstation 建構工具,盡可能減少需要管理的額外基礎架構數量。

依附元件管理

Workstation 存放區會使用 git 子模組和 Bazel 工作區的組合來管理依附元件。Git 子模組會用來擷取外部存放區,而 Bazel 會用來下載建構所需的預先建構和工具鍊。

Bazel 的工具鍊將與工作區規則搭配使用,下載各自的建構規則所需的適當預先建構項目。目前的限制是,許多預先建構的項目都儲存在 CIPD 中,且需要使用 cipd 指令列工具。初始原型需要在開發人員的路徑中使用 cipd 工具。我們正在積極尋找替代方案,並認為這不會是長期的必要條件。

目錄結構

工作站存放區的目錄結構會與 fuchsia.git 目錄結構非常相似,以便為 Fuchsia 開發人員維持一致性。根目錄會包含專案所需的各種中繼資料檔案,以及下列頂層目錄。

  • //src - 用於建構工作站產品的原始碼。
  • //tools - 支援建構作業的指令碼和工具。
  • //src/experiences - 現有的 experiences.git 存放區。
  • //prebuilt - 任何所需的預先建構項目。
  • //third_party - 由 src 目錄使用的第三方程式碼。

建構系統

工作站產品將使用 Bazel 建構系統進行建構。使用 Bazel 的決定與使用 gn/ninja 的 fuchsia.git 不同。這項決定意味著我們無法仰賴 Fuchsia 團隊獲得的專業知識,也無法重複使用現有的建構規則。不過,目前的 gn SDK 不包含任何用於建構或測試 Flutter 應用程式的邏輯,而這類邏輯是 Workstation 產品的主要內容。無論團隊選擇哪個建構系統,都需要編寫這些規則。樹狀結構內存在的範例 Bazel SDK 確實包含一些基本邏輯,可用於建構 Dart 和 Flutter 應用程式。

工作站團隊選擇使用 Bazel 而非 gn/ninja,主要有幾個原因,因為他們認為這會是更吸引人的建構系統。

  • 開放原始碼採用:Bazel 並非最受歡迎的建構系統,但採用率高於 gn/ninja,因此應該更符合開放原始碼社群的需求。

  • 規則生態系統:Bazel 擁有豐富的現有規則生態系統,有助於促進重複使用。

  • 依附元件管理:Bazel 可管理外部依附元件。

  • Fuchsia SDK Bazel SDK 正式化:使用 Bazel 製作 Workstation 產品,可讓我們將變更推送至可供其他專案使用的 Fuchsia Bazel SDK。

  • 單一建構/分析階段:開發人員在使用 Fuchsia 時,常會抱怨不知道為何某個套件或工具未納入建構項目。這通常是因為使用者未在 gn 引數中加入目標。Bazel 會要求使用者明確指定要建構、執行或測試的項目,藉此移除這種失敗模式。

  • 密封式建構:Bazel 預設會執行密封式建構,而 gn 則不會。

在此階段,我們需要編寫建構規則,以便根據 workstation.git buildroot 建構體驗存放區。我們會使用 Bazel 的 new_local_repository 功能。使用這項規則後,我們就能在 workstation.git 中保留 Bazel 專屬的建構規則,以便根據從體驗存放區對應的來源進行建構。請注意,由於 Bazel 建構規則會託管在與實際原始碼分開的存放區,因此這種設定容易導致建構作業中斷。這些中斷情形只會影響正在處理樹狀結構外組件的團隊,而不會影響任何樹狀結構內開發人員。我們瞭解這會造成取捨,但認為不如中斷樹狀結構外開發人員的工作流程,而非樹狀結構內開發人員。樹狀結構外開發人員將負責修正發生的錯誤。

//WORKSPACE

new_local_repository(
    name = "ermine",
    path = "vendor/experiences/session_shells/ermine/shell/",
    build_file = "src/ermine/BUILD.ermine",
)

//src/ermine/BUILD.ermine

flutter_component(name = "ermine_component", ...)
flutter_package(name = "ermine", deps = ":ermine_component")

語言支援

工作站元件目前是以 Dart 和 Rust 編寫,其中 Dart 是目前支援的唯一可用於樹狀結構外開發的語言。workstation_session 和 terminal 元件是以 Rust 編寫,而 Ermine 和 simple-browser 則是以 Dart 編寫。我們會先專注於建構 Dart 元件,同時繼續樹狀結構內建構 Rust 元件,並將這些元件作為平台的一部分提供。

目前有兩個阻斷項目,會導致無法建構樹狀結構外 workstation_session。第一個原因是 workstation_session 使用了多個私人 API,這表示即使有語言支援,也無法在樹狀結構外建構。第二個阻礙因素是缺乏樹狀結構外 Rust 支援。目前,workstation_session 會分割為較小的平台層級元件,以消除對私人介面的依附元件,並探索樹狀結構外 Rust 支援功能。我們會在兩個專案的進展過程中,決定 workstation_session 的命運。如果 workstation_session 已完全從私人介面遷移,但 Rust 支援功能不會很快推出,我們會使用 C++ 重寫工作階段;如果 Rust 支援功能在工作階段遷移前或遷移後不久推出,我們會保留以 Rust 編寫的工作階段。

消毒劑

fuchsia.git 樹狀結構支援各種清理程式,可用於本機開發作業和基礎架構建構工具。在 workstation.git 存放區中支援這些系統並非當務之急,因為我們不會將原始碼移出 fuchsia.git,除非我們已證明建構和組合系統可與已對應的存放區搭配運作。不過,我們應該在有淨化器支援前,將移出 fuchsia.git 的程式碼設為阻斷,因為這會導致與目前設定的回歸。

當本機建構作業正常運作時,我們會新增支援功能,以便傳遞建構時間標記,在本機啟用各種消毒工具。這樣一來,我們就能針對已啟用消毒劑的對應來源進行建構。當我們開始將程式碼移出 fuchsia.git 時,我們會設定建構工具,以符合目前將程式碼提交至 fuchsia.git 的體驗。

您目前可以透過程式碼搜尋功能搜尋 Fuchsia 程式碼。Workstation.git 存放區會以獨立專案的形式新增至這個專案,讓您在線上搜尋及查看該存放區。

程式碼涵蓋率

我們不打算在專案初期啟用 workstation.git 的程式碼涵蓋率,也沒有任何近期計劃。主要原因是大部分的 Workstation 程式碼都是以 Dart 編寫,而 Dart 目前的程式碼涵蓋率支援度不足,因此我們無法花費時間來啟用這項功能。

我們將失去與目前編寫 C++ 程式碼的體驗,因為這確實會顯示逐步增加的程式碼涵蓋率,但在工作站中啟用這項功能的工作範圍太大,目前無法負擔。不過,這確實是與 Fuchsia 建構團隊合作的好機會,讓這些工具更容易供樹狀結構外開發人員使用。

第三方支援

使用 workstation.git 編寫的所有原始碼都必須共用相同的第三方程式庫。其他大型存放區已多次解決支援此功能的工具問題,因此我們不必從頭開始,但這確實代表我們必須為整個專案執行及支援大量工作。

授權法規遵循情況會與 Fuchsia 專案使用的情況相符。第三方存放區的符合性將由存放區的頂層擁有者監控,這也是引入這些依附元件的程式碼審查程序的一部分。

我們目前沒有任何確切的計畫,針對建構期間和程式碼檢查期間檢查授權,並產生 NOTICE 檔案。我們需要研究如何在 fuchsia.git 存放區中執行這項操作,並將該邏輯移植至此存放區。

二進位檔大小監控

監控二進位檔大小對於專案的長期健康狀態至關重要。Fuchsia 建構系統中提供工具,可監控每次提交時產生的二進位檔大小。針對 Workstation 產品重新建構這些系統,超出本專案初期階段的範圍,但我們最終還是需要新增這些系統。

我們需要調查這些系統與目前 fuchsia.git 建構系統的耦合程度,看看我們是否可以直接以目前形式整合這些系統,或是需要進行分離作業。如果我們需要將工具與建構系統分離,就應著重於讓這些工具可重複使用,以便日後擴展至其他產品整合器。

效能測試

目前有專案正在進行,以便在 Workstation 產品中新增效能監控功能。這項專案已在進行中,專注於讓監控功能可供樹狀結構外使用者使用,但僅使用公開 SDK 提供的工具。我們預計在程式碼移出 fuchsia.git 後,將這些測試移至 workstation.git 存放區。

擁有者

與 fuchsia.git 的貢獻者相比,workstation.git 存放區的初始貢獻者組合會較小。因此,在本專案的初期階段,我們不會優先執行 OWNERS 檔案,但會持續將這些檔案新增至適當的目錄,以利溝通。當我們開始將程式碼從 fuchsia.git 移出時,我們會引入 OWNERS 檔案,並針對程式碼審查強制執行與 fuchsia.git 相同的規則。

由於 workstation.git 存放區會在同一個專案下託管,因此對該存放區的貢獻會受到與 fuchsia.git 存放區相同的政策規範。

錯誤追蹤

這個存放區會使用現有的 Fuchsia Issue Tracker 追蹤錯誤。之所以使用 Fuchsia Issue Tracker,是因為它已設為追蹤 Fuchsia 錯誤,而且工作站產品的板卡支援功能仍會保留在 fuchsia.git 中。頂層工作站元件可用於一般分類,而有幾個現有元件可用於追蹤工作站產品的各種功能。

構件的流程

為了在 fuchsia.git 以外組合 Workstation 產品,我們需要提供 Fuchsia 平台的預先建構項目,供 Workstation 產品使用。這表示我們會有兩種類別的構件,一種是組成平台的構件,另一種則是用於組合最終工作站產品映像檔的構件。平台映像檔會提前建構,以供 workstation.git 存放區使用,而工作站元件則會在最終產品映像檔組合時建構。組成平台的一系列構件目前尚未明確定義,因為平台會持續演進,但工作站元件將包含 workstation_session、Ermine 和 simple-browser。請注意,即使是僅支援 Workstation 產品的驅動程式庫程式,我們也不建議將任何驅動程式庫開發作業移至樹狀結構外。

為了讓 workstation.git 使用預先建構的構件,我們需要設定 fuchsia.git 建構工具來建立預先建構項目,以及自動推送工具,將構件拉入 workstation.git。我們可以擴充目前正在執行的其中一個建構工具,但我們尚未徹底調查是否可行。

fuchsia.git 建構工具會每天執行一次,並建構 Fuchsia 平台。我們還需要瞭解實際建構的內容,才能決定這個建構工具的確切設定方式。建構工具會將所有適當的構件上傳至 Autoroller 可使用的位置。上傳這些構件的精確位置和機制仍待確定。產物中會包含資訊清單檔案,其中包含用於建立平台的所有依附元件版本。這包括但不限於 SDK 版本、experiences.git 版本、Flutter 和 Dart 版本、Fuchsia 工具鍊版本等。

自動輪播器會每天執行多次,檢查平台的新版本。多次執行這項操作,可確保我們能取得最新版本,不受當天不同時間可能出現的異常發布或建構作業影響。自動滾動器會輪詢最新版本的平台,並擷取這些構件。輪替器也會讀取資訊清單檔案,其中包含所有依附元件的版本,並更新這些版本。這可確保平台和各種依附元件之間的版本不會出現差異。

所需資料大多是包含檔案系統分區的檔案,例如 fuchsia.zbi 和 fvm.sparse.blk。這些檔案包含啟動作業所需的所有資料,以及「base」和「cache」清單中的所有套件。這些檔案會收集到 .far「產品套件」中,而這個套件網址中的中繼資料會包含所有必要的中繼資料,以便使用相符的 SDK 建構元件套件。您可以修改「產品套件」中包含的系統分區,將根據此中繼資料建構的套件附加至基礎和快取。此外,您也可以並行執行建立獨立的樹狀結構外圖片組合器的工作,因此「產品套件」中所包含的特定構件清單會因新工具的 API 而有所變動。

每日建構工具會以可讓我們存取特定版本的「產品套件」方式上傳構件。固定存放區會包含所有平台版本的參照,讓 Roller 能夠識別最新版本或特定版本,以便與 ABI 相容。目前我們正在研究這項提案以外的特定程序,以便啟用這項功能。

組合最終產品時,建構系統應先下載「產品套件」,並以網址識別。然後下載相符的 SDK。(SDK 也可以在「產品套件」中綁定)。它應根據該 SDK 建構套件,為每個套件建立 meta.far 檔案,並將所有必要的 Blob 收集到單一位置。接著,組合工具會將這些 Blob 和套件附加至「產品套件」,產生完整的產品建構。產生的構件也應包含產生 OTA 套件所需的所有必要資訊。

ABI 注意事項

如果將 Workstation 產品與平台分開編譯,就可能會發生 ABI 不相容的問題。我們必須確保,Workstation 元件一律會使用 SDK 發布版本進行編譯,該版本必須等於或舊於 RFC-0002 中所述的平台發布版本,且必須在相容性視窗內。為確保維持這個不變量,我們會在與平台一併推出的中繼資料中加入 SDK 版本,並更新 workstation.git 存放區,以便使用這個版本的 SDK。

請注意,這個 ABI 考量事項必須擴展至為 Workstation 產品提供程式碼的其他花瓣,例如 Flutter 和 Dart 執行程式。為了盡可能降低這些花瓣造成 ABI 損壞的風險,我們會先將這些花瓣當作平台的一部分推出,也就是說,這些花瓣已在 Fuchsia 的全域整合中通過驗證。

當我們開始將花瓣從平台介面移出時,需要確保這些花瓣與我們的產品相容。對於回傳至 Fuchsia Global Integration 的 petal,我們可以在建構平台時,將版本的中繼資料傳播出去。不過,未來某些依附元件將不會納入 Fuchsia Global Integration,也就是說,我們不會在平台發布中加入版本資訊。我們需要使用平台版本管理功能,確保我們納入正確的版本,並找出處理過時版本的方法。

實作

從 fuchsia.git 建構及組合工作站產品的程序會分成多個階段,每個階段都以先前的階段為基礎。由於目前正在開發支援樹狀結構外開發的系統部分,因此必須採用這種分階段方法。

第 1 階段

讓工作站建構樹狀結構外項目的初始階段,就是設定開發環境。我們將建立 workstation.git 存放區來託管程式碼。這個存放區會包含引導程式碼,讓使用者可以開始使用。存放區會使用 Bazel 工作區和 git 子模組來管理第三方程式碼、預先建構項目,以及經驗存入供應商的存放區。

第 2 階段

第二階段將著重於設定建構系統,以建構 Flutter 元件。我們會使用 fuchsia.git 中現有的 Bazel 規則,作為編寫建構規則的起點。最終狀態是指我們可以成功建構 Flutter 元件,並在已執行中的裝置上啟動。

在設定建構 Flutter 元件的規則的同時,我們將探討如何使用產品組合工具進行樹狀結構外組合。您可以手動執行這項程序,只要將 fuchsia.git 中建構的所有構件複製到 workstation.git 存放區的 out 目錄,然後嘗試建立可啟動的映像檔即可。結束狀態是指我們可以使用在樹狀結構外組合但在樹狀結構中建構的映像檔,為裝置佈建時的狀態。

第 3 階段

這項轉換作業的第三階段,就是將所有部分整合在一起,組合成完整的產品。這包括設定建構平台構件所需的所有基礎架構,並依時程表將這些構件上傳至 TUF 存放區。這個建構工具會在 Fuchsia 基礎架構中執行。workstation.git 存放區會透過 autoroller 推出新版本。Autoroller 會更新 workstation.git 存放區中的資訊清單檔案、執行整合測試,並提交這項變更。這與 fuchsia.git 不同,後者會將版本更新內容提交至整合存放區,以協調版本變更。

建構和組合的工作流程如下:

  1. 更新可識別平台版本和所有依附版本的資訊清單項目,即可推出新版平台。需要設計版本的讀取和識別方式。
  2. 使用 Bazel 和 git 下載適當的預先建構項目和第三方存放區,以便建構樹狀結構內的元件。
  3. 使用平台下載工具,從 TUF 存放區下載所有平台構件。
  4. 建構樹狀結構內元件。
  5. 將已建構的元件和預先建構的元件組合成最終映像檔。

成效

由於這項專案只會建構及組合,因此不會對工作站產品的效能造成任何影響。不過,由於工作站開發人員不必建構平台,因此我們應該會開始看到他們的建構時間大幅改善。

安全性考量

我們會重複使用 fuchsia.git 使用的基礎架構,但我們需要確保 Workstation 是以安全的方式建構及發布。我們將與安全性和基礎架構團隊合作,建立安全的發布程序和建構管道。

工作站產品僅供參考,但我們仍會確保遵循適當的安全性通訊協定。一旦我們開始著手任何類型的版本發布作業,就必須與安全性團隊合作,確保我們以符合安全性規範的方式建構版本。

隱私權注意事項

目前沒有任何影響隱私權的因素需要考量。我們會使用不會收集使用者資料的開放式工具。

測試

Workstation 產品會在每個提交內容上執行一組測試。這些測試包括單元測試、整合測試、e2e 測試和效能測試。這些測試的程式碼會在工作站元件程式碼移植至 worksation.git 時,一併移植至 workstation.git 存放區。

這些測試的邏輯位於 experiences.git 中,因此我們可以執行這些測試,因為我們會將這個存放區對應至 workstation.git,直到實際移動程式碼為止。所有這些測試都會使用公開 SDK 提供的程式碼和工具,因此我們可以將這些測試執行在樹狀結構外,但需要更新建構系統,確保這些測試可以在 fuchsia.git 以外建構及執行。

系統會在每一次將 commit 提交至 workstation.git 存放區時執行測試,以防回歸。您必須與基礎架構團隊合作,瞭解如何在 CQ 中建構及執行這些測試。目前的基礎架構會假設 fuchsia.git 已存在,因此我們需要開發一種方法,不受建構系統和存放區版面配置影響。

說明文件

我們只需要在 workstation.git 中新增說明文件,說明如何設定開發用存放區。Workstation 開發作業會保留樹狀結構內,因此我們應繼續將文件指向該工作流程。

缺點、替代方案和未知事項

另一種做法是只在 Fuchsia 樹狀結構中執行所有這類工作,但使用 SDK 中完全存在的工具。我們放棄這種做法,是因為這會讓我們很容易隱藏私人介面的用途。將組件完全移至樹狀結構外,我們就必須完全依賴 sdk。

我們仍不確定要將哪些內容上傳至 TUF 存放區、上傳內容的格式,以及我們上傳的構件中中繼資料的格式。我們認為這些具體細節會在我們開始處理整個程序時確認,並視需要修改此 RFC。