| RFC-0124:去中心化產品整合:構件說明和傳播 | |
|---|---|
| 狀態 | 已接受 |
| 區域 |
|
| 說明 | 描述及傳播構件的機制,適用於去中心化產品整合。 |
| Gerrit 變更 | |
| 作者 | |
| 審查人員 | |
| 提交日期 (年-月-日) | 2021-03-30 |
| 審查日期 (年-月-日) | 2021-08-30 |
摘要
本 RFC 說明一種機制,可讓 Fuchsia 來源樹狀結構或花瓣存放區的來源或預先建構的構件,用於組裝 Fuchsia 產品。
這項機制包含兩個重要層面:
- 說明構件,使用適合的元資訊,將每個構件的相容或所需版本和變體選取到要組裝的產品中。
- 傳播構件,以便從構件的來源存放區和使用構件的整合存放區中,識別、參照及存取構件。
提振精神
如分散式產品整合開發計畫文件所述,我們希望在 Fuchsia 來源樹狀結構以外組裝產品。為此,您必須在 Fuchsia 來源樹狀結構外部執行獨立映像檔組裝工具,並提供必要的來源或預先建構的構件。Fuchsia 來源樹狀結構提供 Zircon (Fuchsia 核心) 和系統套件等構件。各種花瓣存放區會提供其他元件的套件,例如產品專屬元件和執行器。
Fuchsia 來源樹構件會定期推出新版本。 同時,Fuchsia SDK 的版本也會產生,並由花瓣存放區定期匯入,進而用於以花瓣存放區的版本節奏產生自己的 Fuchsia 構件。
一般來說,花瓣存放區的發布週期與 Fuchsia 來源樹狀結構的發布週期並不一致,且版本 ID 也不同。花瓣可以選擇與 Fuchsia 同步發布,例如在每次發布 Fuchsia SDK 時,也發布自己的版本。
每個這類構件版本也可能以不同變體產生,例如適用於各種處理器架構的可執行檔、偵錯與最佳化變體、以「穩定」與「最新」標籤指定的變體,用來區分主幹版本與穩定分支版本,或是啟用或停用建構時間功能的變體。
如要在與 Fuchsia 來源樹狀結構不同的整合存放區中,從這類構件組裝產品,必須讓整合存放區可存取這些構件。此外,產品整合所需的構件必須針對產品的每個版本和變體,在構件的適當版本和變體中選取。
目前的產品整合程序稱為「全球整合」。在稱為「滾動」的程序中,花瓣存放區的預先建構構件會匯回 Fuchsia 來源樹狀結構。接著,系統會從最新來源修訂版本的 Fuchsia 來源樹狀結構中,組裝所有構件,並搭配已整合至整合存放區的固定版本中,來自 Petal 存放區的預先建構套件,組裝成最終建構產品。這項程序如圖 1 所示。
圖 1 - 全球整合程序 (圖例)

這個程序有幾個缺點:
- 產品組裝設定會保留在 Fuchsia 來源樹狀結構中,而不是由
- Fuchsia 系統的版本一律會比任何以 Fuchsia SDK 建構的 Petal 構件版本新,因為 Fuchsia 系統是從 Fuchsia 來源樹狀結構的最新來源修訂版本建構而成,但 Petal 構件的 SDK 是從較早的修訂版本建構而成。
- 如果不同花瓣的構件彼此之間有版本相容性需求 (例如 Flutter 執行元件和 AOT 編譯的 Flutter 應用程式),則只能在同一個捲動器中一併捲動這些構件,才能維持相容性。
- 即使花瓣構件受產品擁有者控管,用於產品整合的版本也不受控管,因為讓新版構件可供產品整合的推出程序,會與所有其他花瓣構件的所有其他推出程序協調,且可能因任何其他產品的整合測試失敗而遭到封鎖。
建議的去中心化產品整合程序可改善這些缺點,因為這項程序允許在 Fuchsia 存放區外部組裝產品,直接解決上述問題:
- 產品組裝設定會儲存在各產品的獨立整合存放區,由產品擁有者控管。
- 您可以選取與建構花瓣構件的 Fuchsia SDK 相容的版本,確保產品所有構件的 ABI 相容性。舉例來說,Fuchsia 發布版本號碼的第一個元件會遞增,每次建立 Fuchsia 發布分支版本時,都會遞增這個元件,藉此表示類似 RFC-0002 中規定的 ABI 修訂版本,並對應至必要的 6 週 ABI 相容性窗口。因此,產品中的所有構件都可與 SDK 建構時的 Fuchsia 發布版本號碼的相同第一個元件對齊。
- 您可以直接選取不同花瓣存放區的構件版本,確保滿足相互相容性需求,並根據直接指定的限制條件升級至下一個版本,不必為構件配對設定專屬的滾動器。舉例來說,您可以直接選取相同 Flutter 和 Dart 發布版本號碼的 Flutter 應用程式和對應的 Flutter 執行元件。
- 產品可以按照自己的發布週期選取所有貢獻構件的版本和變體,不必等待其他產品也選取該版本。
利害關係人
協助人員:abarth@google.com
審查人員:aaronwood@google.com (Assembly)、etryzelaar@google.com (SWD)、 wittrock@google.com (SWD)、atyfto@google.com (Fuchsia Build Infrastructure)、 marvinpaul@google.com (TUF Server Infrastructure)、jsankey@google.com (Security)、enoharemaien@google.com (Security & Privacy)、schilit@google.com (相關 RFC 作者)。
諮詢對象:軟體推送團隊、代管 OS 團隊和基礎架構團隊的成員。
社交化:除了與諮詢團隊討論外,這份 RFC 草案也已傳送至 FEC 討論郵寄清單,供大家提出意見。
設計
在介紹設計總覽之前,我們會先說明或釐清一些術語和概念。
術語
在以下段落中,粗體字詞的意義由周圍文字說明。
Fuchsia 來源樹狀結構包含多個不同的 Git 存放區,這些存放區會由名為 jiri 的工具,根據 integration.git Git 存放區中保留的設定,一起設定為一個來源樹狀結構。其中最重要的 Git 存放區是 fuchsia.git,但還有許多其他存放區,包括第三方存放區。jiri 設定也會控制預先建構的構件是否納入來源樹狀結構的專用部分。預先建構的構件本身會儲存在名為 CIPD 的儲存服務中,並受到修訂版本控制;而說明 CIPD 中預先建構構件位置和修訂版本的 jiri 設定,則會受到 integration.git 存放區的 git 修訂版本控制。
名為「Roller」的建構工作會定期執行,嘗試更新 Fuchsia 來源樹狀結構中預先建構的構件版本。如果 Fuchsia 樹狀結構的所有所需建構產品都能使用更新版構件建構及測試,系統就會將 Fuchsia 樹狀結構的變更內容提交,而更新版構件現在會是已釘選的版本。不同預先建構的構件可使用不同的捲動器。
在現狀下,Fuchsia 來源樹狀結構同時扮演兩種角色:Fuchsia 產品中使用的許多構件的來源存放區,以及整合存放區,每個 Fuchsia 產品都是由各個部分組裝而成。
構件是指產品組裝過程中使用的任何成分。這類構件是從來源存放區取得,可以直接做為來源項目之一,也可以做為在存放區中執行建構程序所取得的建構產品。這類構件大多是預先建構的 Fuchsia 套件,但也包含 Fuchsia 核心 Zircon,且可能很快就會包含子組件規格檔案。Zircon 核心和預先建構的套件是預先建構的構件;子組件規格檔案是來源構件。
從來源存放區取得的構件最終會發布至構件商店。您可以手動發布,也可以排定發布時間,讓系統自動發布。無論採用哪種方式,產生的構件都會發布至來源存放區的專屬構件商店。構件存放區可以是任何位置,只要能從來源存放區外部找到構件,不必參照來源存放區,更不用執行建構程序即可。因此,Artifact Store 可以是 CIPD 目錄、GCS bucket 或 TUF 存放區。就此處設計的程序而言,特定類型的構件商店並非必要。
TUF 存放區用於將軟體傳送至 Fuchsia 裝置、將新重建的套件傳送至開發人員 Fuchsia 裝置或開發環境中的模擬器,以及將 OTA 更新傳送至正式版 Fuchsia 裝置。在內容定址儲存服務上使用 Fuchsia 的 TUF,特別適合儲存 Fuchsia 套件,由於許多構件都是 Fuchsia 套件,因此這個設計偏好使用 TUF 存放區做為構件儲存空間。
屬性是描述構件的鍵/值屬性,可區分構件的版本和變體。鍵會說明變異性的維度,值則是構件在該維度上的位置。屬性會一致地說明構件的版本和變體。在多數情況下,不需要區分描述版本的屬性和描述變體的屬性。構件發布者可以指定下列屬性:
- CPU 架構變數,
x64與arm64。 debug與optimized彙整變體。- 構件建構來源存放區的提交版本。
- 建構用於建構構件的參數。
- 用於建構構件的 Fuchsia SDK 版本。
- 建構構件的語意版本。例如 Chromium 發布版本 (如
M88.xxx) 或 Cast 發布版本 (如1.56.xxx)。 - 實作後,API 級別和 ABI 修訂版本會如 Fuchsia 系統構件的 RFC-0002 所述。
- 花瓣提供的 API 級別或 SDK 版本目前不在 RFC-0002 的範圍內,但與系統 ABI 同等重要。舉例來說,Flutter 應用程式建構時使用的 Flutter SDK 發布版本。
遞移屬性:部分屬性描述構件的遞移屬性,因為這些屬性與構件建構來源的輸入內容屬性相關。舉例來說,Fuchsia SDK 版本或 Flutter 版本實際上是前置構件的屬性,用於建構所述構件。預計這類遞移屬性會進一步擴展。因此,屬性值可以是物件,其中又包含鍵/值組合,依此類推。
依附元件屬性:成果的依附元件 (包括版本和變數) 也可以表示為屬性。不過,Fuchsia 套件是密封的,因此已包含依附元件。因此,依附元件通常不會經常出現在 Fuchsia 構件的屬性中。
現況
在目前的全球整合程序中 (如圖 2 所示),花瓣建構程序會使用 CIPD 目錄做為構件商店。構件商店會將構件保留在路徑名稱下 (在 CIPD 中稱為「套件」,與 Fuchsia 套件沒有直接關係)。CIPD 支援在「套件」的相同路徑名稱下儲存多個「執行個體」,並將「標記」和「參照」附加至執行個體。變體中繼資訊會編碼至儲存構件的路徑名稱元件。版本中繼資訊會編碼至 CIPD 套件執行個體的標記和參照中。產品建構程序會透過滾動取得構件的固定版本,並一律從花瓣構件的固定版本建構產品。
圖 2 - 目前的系統結構

透過構件商店傳播擴充的中繼資訊
這裡提出的設計會變更構件商店的結構,以便保留發布構件的元資訊屬性。然後,產品可以根據屬性值條款中指定的條件,選取合適的構件。
這項設計包含三個額外的設定檔,以及三個用於處理設定檔的工具,可與構件商店互動。檔案會保留在構件商店 (artifact_groups.json) 和產品整合存放區 (artifact_spec.json) 中。artifact_lock.json如圖 3 所示,工具 upload、update 和 fetch 會對檔案和構件執行作業,如下所示:
- 從 Petal 或 Fuchsia 建構程序發布一組新構件時,系統會在與來源存放區相關聯的構件商店中建立新的構件群組。發布構件的屬性會記錄在
artifact_groups.json檔案中,該檔案也會保留在構件商店中。- Petal 建構程序會使用
upload工具,將新發布的構件發布至構件商店,並更新artifact_groups.json檔案。
- Petal 建構程序會使用
- 在產品整合存放區中,
artifact_spec.json檔案會保留清單,指出要從哪些構件商店取得構件,以在這個整合存放區中組裝產品,以及要使用哪些屬性。update工具用於選取實際要用於組裝的構件集,方法是使用整合存放區中的artifact_spec.json檔案,以及artifact_spec.json檔案中列出的所有構件商店中的artifact_groups.json檔案。
update工具選取的構件集會儲存在artifact_lock.json檔案中。fetch工具會下載artifact_lock.json檔案中提及的所有構件,以便在整合式存放區中提供給產品建構程序。
這些工具與建構規則執行的關聯,取決於產品整合存放區中使用的特定建構系統。詳情請參閱「實作」一節。
這些工具允許整合存放區中存在多個 artifact_spec.json 和 artifact_lock.json 檔案。
圖 3 - 所有協作零件的關係

構件存放區內的邏輯結構
成果商店中成果和成果群組的邏輯結構如下例所示:
└── artifact_groups
|
├── 92d483e5-ac7d-4029-a7db-e2ee6a8365c7
| |
| ├── web_engine
| |
| └── cast_runner
|
└── c907ff3f-cb15-4a7f-bb79-8cc23c0ff445
|
├── web_engine
|
└── cast_runner
一組構件的每個版本都會顯示不透明的名稱,而每個構件都會以可辨識的名稱顯示為群組中的項目。
這個結構會連同發布版本和個別構件的相關屬性,以 JSON 資料結構的形式記錄在 artifact_groups.json 檔案中,詳情請見下文。
構件和群組名稱的用途
JSON 資料會使用群組名稱和構件名稱,將記錄的屬性與所描述的構件建立關聯。這兩個群組和構件的名稱,都會用於運算式中,以便在 artifact_spec.json 檔案中將構件選取至產品組裝工作區。此外,構件名稱也會做為檔案名稱,fetch 工具會將下載的副本儲存在這些檔案中。
不過,這兩個名稱都不會用於指定構件在構件商店中的儲存位置。所有構件都會儲存在內容位址下,且每個構件的內容位址都會記錄在 artifact_groups.json 中做為 merkle 屬性。
使用的內容位址是構件直接內容的 Fuchsia Merkle 根。部分構件 (尤其是 Fuchsia 套件) 會以其他儲存空間元件 (「Blob」) 表示,這些元件會遞移包含在構件的直接內容中。這些額外元件會儲存在內容地址下,但不會在 artifact_groups.json 中明確提及。
唯一性不變量
Artifact Store 中有幾項不變的獨特性需要維護。這些不變量可確保構件可透過參照名稱和屬性明確選取:
- 在整個歷史記錄中,構件商店內的群組名稱不得重複。
- 每個群組中的構件名稱不得重複。
- 一個群組中每個構件的屬性,在構件商店中所有同名構件中都不得重複。
將新的構件群組新增至構件商店時,upload 工具會維護這些不變的獨特性。update 工具也會檢查唯一性,如果存取的所有 artifact_group.json 檔案不符合不變量,就會拒絕計算更新。構件商店本身不需要在維護這些不變量方面扮演任何角色。
群組名稱不透明
您可能會想以屬性值命名構件群組,讓構件商店更容易理解或瀏覽。不過,只有在屬性數量不多且固定時,這個方法才適用。一旦屬性集擴展到許多屬性,而且是開放的屬性集,光是從中建構名稱就會變得相當繁瑣,因為即使是單一屬性值集 (例如架構是第一個、最後一個還是中間的),可能的排列組合數量也會呈指數成長。此外,閱讀這類名稱不再輕鬆,維護不變的唯一性 (尤其是跨歷史記錄) 也更加麻煩。
因此,由於這項設計的目標是支援大型開放屬性集,因此群組名稱會選擇不透明,並滿足必要的不重複不變量。在上述範例中,群組名稱是隨機 UUID。替代做法是使用單調遞增的填補整數。
artifact_groups.json 檔案
artifact_groups.json 檔案會列出所有群組、所含構件,以及構件商店中的相關聯屬性。
以下範例顯示與上述構件存放區範例對應的 artifact_groups.json。屬性會與構件群組建立關聯,因此所有屬性都會套用至群組中的所有構件。屬性只能套用至個別構件。
這項設計並未規定屬性集。所有屬性都是由建構和發布程序選取及指派,該程序會在來源存放區中產生構件。指派的屬性僅需維持上述不變的唯一性。
{
"schema_version": "https://fuchsia.dev/schemas/artifact_groups_schema.json",
"version": 15,
"artifact_groups": [
{
"name": "92d483e5-ac7d-4029-a7db-e2ee6a8365c7",
"attributes": {
"petal": "chromium.org",
"version": "chrominum_release_20210304",
"architecture": "arm64",
"sdk_version": "2.20210303.3.1",
"creation_time": "1622696983",
"commit": "b26e44e9910608a2d0aec9b38e003a04a2da06df"
},
"artifacts": [
{
"name": "web_engine",
"merkle":"90f67b10ded655852acb78a852ac5451486fc1e7378ce53368386244ce8f6e66",
"type": "package",
"attributes": {
"runner_version": "2.20210301.1.3"
}
},
{
"name": "cast_runner",
"merkle": "3394db36d228f4c719d055c394938c5a881ca6eea7ad3af0ad342e764cadc8b3",
"type": "package"
}
]
},
{
"name": "c907ff3f-cb15-4a7f-bb79-8cc23c0ff445",
"attributes": {
"petal": "chromium.org",
"version": "chrominum_release_20210402",
"architecture": "arm64",
"sdk_version": "2.20210303.3.4",
"creation_time": "1622157425",
"commit": "2dd76ad2298dfb869ef83c10b84b62485dc8a573"
},
"artifacts": [
{
"name": "web_engine",
"merkle": "acb78a852ac5451486fc1e7378ce53368386244ce8f6e6690f67b10ded655852",
"type": "package",
"attributes": {
"runner_version": "2.20210225.1.4"
}
},
{
"name": "cast_runner",
"merkle": "19d055c394938c5a881ca6eea7ad3af0ad342e764cadc8b33394db36d228f4c7",
"type": "package"
}
]
}
]
}
artifact_groups 清單中的每個群組物件都包含 3 個屬性:name 是群組名稱、artifacts 是群組中的構件清單,而 attributes 則是群組中所有構件共用的屬性。
僅適用於單一構件的屬性會直接納入代表該構件的物件。這個構件的屬性會附加至群組的屬性,以取得完整的構件屬性集。
版本號碼會不斷增加。update 工具會使用這個號碼,防止意外回溯至舊版 artifact_groups.json 檔案。
構件群組及其屬性的可變動性
在一般使用情況下,一組構件的每個發布版本都會記錄為新群組。因此,群組名稱、其中的構件集,以及大部分的屬性在概念上都是不可變更的。例外狀況是反映構件發布後產生的構件資訊的屬性。舉例來說,在構件發布後,如果對構件進行手動測試,測試結果狀態可能會變更。反映這類資訊的屬性可能會更新。
不過,原則上,構件群組的內容、名稱或屬性可能會隨時間變更。可以想見,這項功能可用於產品組裝流程,但不會用於建議的應用程式 (請參閱下方的實作部分)。
產品建構程序
整合存放區中的產品建構程序會建立 artifact_spec.json 檔案,以下稱為「規格檔案」。這個檔案會列出產品在整合存放區中組裝時所需的構件、取得構件的構件商店,以及構件屬性的模式和限制。並說明構件商店的類型,一個規格檔案中可以同時存在多種不同類型的構件商店。
具體來說,預先建構的構件可儲存在整合存放區本身,並在規格檔案中參照,就像來自「本機」類型的構件商店一樣。
整合式存放區中的產品建構程序會使用 update 工具,比對規格檔案中提及的所有構件商店中的 artifact_groups.json 檔案,並計算要使用的特定構件變體和版本組合。這組資料會記錄在 artifact_lock.json 檔案中。這個檔案應做為存放區中的來源檔案提交。
fetch 工具會讀取 artifact_lock.json 檔案,並將所有構件下載至整合存放區。這些構件不應做為來源檔案提交至存放區。不過,構件是透過從 artifact_groups.json 檔案取得的內容地址,在 artifact_lock.json 檔案中識別。這可確保 artifact_lock.json 的已提交內容完全決定提供給建構作業的構件內容,因此就 artifact_lock.json 檔案中選取的構件而言,產品組裝建構作業是密封且可重現的。
實作
這裡提出的設計會先用於將工作站產品整合功能移至獨立存放區。
artifact_spec.json 的必要詳細資料,以及如何根據 artifact_groups.json 檔案處理這些資料以產生 artifact_lock.json 檔案,請參閱另一份 RFC。
遷移現有花瓣和產品
只要 Fuchsia 來源樹狀結構 (從 integration.git 設定) 仍需要花瓣預先建構,就必須上傳至 CIPD,供 Fuchsia 來源樹狀結構中的 gn 建構規則使用,並上傳至樹狀結構外產品使用的構件商店。最終,Fuchsia 來源樹狀結構中將不再需要某些花瓣預先建構項目,上傳至 CIPD 的作業也會停止。
我們無意取代使用 jiri 設定 Fuchsia 來源樹狀結構的機制,因為所有 Fuchsia 平台構件、SDK 和部分產品都會繼續從 Fuchsia 來源樹狀結構建構。
構件存放區
工作站及其花瓣的實作項目會使用 TUF 存放區做為構件商店。TUF 存放區的 targets.json 檔案中只有 artifact_groups.json 檔案的項目。構件本身會儲存在 TUF 伺服器基礎架構維護的內容定址 blob 儲存空間中 (用於 Fuchsia),而對應的 blob 位址則會記錄在 artifact_groups.json 檔案中。
此外,構件也可以列在目錄和構件名稱下的 targets.json 中,但這個設計並未要求這麼做。(為確保歷史記錄完整性,我們在此提及這項做法,因為過去有人會預期看到 targets.json 項目。請參閱下方的替代方案一節。
Fuchsia 套件結構依附元件
這裡建議的三種工具會與構件商店互動 (上傳、更新、擷取),並對 Fuchsia 套件進行操作,因此會對 Fuchsia 套件的結構做出假設。具體來說,Fuchsia 套件應包含 meta.far Blob,其中含有其他 Blob 的內容位址 (以 Merkle 根表示),這些 Blob 也屬於該套件。meta.far 中參照的 Blob 清單是使用 Fuchsia SDK 提供的工具取得,因此構件儲存空間工具 (上傳、更新、擷取) 不會依附於 meta.far 的內部結構。
工具與建構規則的關係
upload、update 和 fetch 工具與建構規則執行的關聯,取決於來源存放區和產品整合存放區中的特定建構系統,以及建構執行的基礎架構。
建構系統完成建構後,預計會執行 upload 工具。
通常,update 工具應在建構規則之外使用,也就是在建構作業執行前使用。
fetch 工具可在執行建構規則前使用,也可以在建構系統支援的情況下,做為建構系統執行作業的一部分。工作站會使用 bazel 做為建構系統,支援在所謂的「工作區規則」中設定輸入檔案集。
工具可執行檔的名稱
工具 upload、update、fetch 最終可能會以其他名稱實作,而非本設計中使用的概念名稱。具體來說,這些工具可以實作為 ffx 工具的外掛程式,或是由 bazel 建構規則產生的工具。初始原型會將這些項目實作為名為 artifact_upload.py、artifact_update.py 和 artifact_fetch.py 的 Python 指令碼。
檔案語法
artifact_groups.json 檔案的語法由下列 JSON 結構定義提供。artifact_spec.json 和 artifact_lock.json 檔案的 JSON 結構定義記錄在另一個 RFC 中。
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "https://fuchsia.dev/schemas/artifact_groups_schema.json",
"type": "object",
"additionalProperties": false,
"required": [
"contents",
"schema_version",
"version"
],
"properties": {
"schema_version": {
"type": "string"
},
"version": {
"type": "integer"
},
"artifact_groups": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"type": "string"
},
"attributes": {
"type": "object"
},
"artifacts": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"name",
"merkle",
"type",
],
"properties": {
"name": {
"type": "string"
},
"merkle": {
"type": "string"
},
"attributes": {
"type": "object"
},
"type": {
"type": "string"
}
}
}
}
}
}
}
}
}
檔案語意
如要瞭解 artifact_groups.json 的檔案格式語意,請參閱這篇文章。artifact_spec.json 和 artifact_lock.json 的詳細語意同樣記錄在另一個 RFC 中。
{
"schema_version": SCHEMA_VERSION,
"version": VERSION,
"artifact_groups": [
ARTIFACT_GROUP,
...
]
}
SCHEMA_VERSION
字串,指出
artifact_groups.json的 JSON 結構定義網址。
版本
指出
artifact_groups.json版本號碼的整數。 發布新版本時,這個數字應會增加。
ARTIFACT_GROUP
每個 ARTIFACT_GROUP 都是物件,格式如下:
{
"name": NAME,
"attributes": ATTRIBUTES,
"artifacts": [
ARTIFACT,
...
]
}
名稱
這個字串提供參照這個構件群組的方法。
屬性。
發布商定義的物件。
ARTIFACT
每個 ARTIFACT 都是物件,格式如下:
{
"name": NAME,
"merkle": MERKLE,
"type": TYPE,
"attributes": ATTRIBUTES
},
名稱
包含這個構件名稱的字串。
MERKLE
成果 Merkle 根的字串。
類型
包含這項構件類型的字串。如果
TYPE為"package",則 Merkle 根參照的 Blob 中的這個構件是 Fuchsia 套件的meta.far,且meta.far中遞迴參照的 Blob 一律會與 meta.far Blob 一併處理。否則,構件只會包含列出 Merkle 的單一 Blob。
屬性
與上述 ATTRIBUTES 類似的物件。您可以在這裡定義構件專屬屬性。
安全性考量
本 RFC 中的設計不會改變現有參與者之間的信任模型。這項機制只會變更儲存結構,不會變更使用構件商店的參與者之間,或參與者與構件商店之間的信任關係。
信任模式
如同目前使用 CIPD 做為構件存放區的情況,產品建構程序需要信任構件存放區。目前這項信任機制是根據構件商店對 Petal 和 Fuchsia 建構程序套用的存取控制和驗證機制,以及對建構基礎架構和環境的依賴,將構件商店的設定名稱解析為存取正確的構件商店。
建立更多構件商店和產品整合存放區後,需要評估這些商店和存放區的信任基礎,並相應評估組裝產品的可靠性。
日後可能會建立目前使用機制以外的其他機制,例如驗證簽章 (如 TUF 存放區中的簽章)。這裡設計的機制可支援傳播相關資訊,以評估可信度,但這類資訊的建立是正交的。
特別是針對 TUF 簽章,請務必注意,這類簽章只會提供證據,證明存放構件的存放區值得信賴。單獨使用這項功能無法完整評估從中取得構件的可靠性,因為這還取決於簽署金鑰的控管、產生構件的建構程序可靠性,以及建構程序使用的遞移來源和工具可靠性。以目前用於 Fuchsia 產品的 TUF 實作項目為例,該項目會簽署上傳至維護存放區服務的所有構件,因此也取決於 ACL 的完整性,以及允許用戶端存取該服務的驗證機制。
多個 Petal 建構程序發布至相同構件商店
建議發布來源存放區不要共用構件商店,這樣就不必與伺服器共用信任關係 (無論信任關係的建立方式為何)。舉例來說,在 TUF 實作中,發布商不必共用簽署金鑰。
多個花瓣建構程序發布至相同構件商店時,也可能會造成潛在的妥協。舉例來說,某個發布者可能會覆寫其他發布者發布的構件。但這超出本 RFC 的範圍,因為在本 RFC 中,發布至構件商店的所有花瓣建構程序都由同一機構運作,因此可以妥善協調。如果想將這項功能擴展至多個機構,則需要設計不同的協調模型。
效能
隨著 artifact_groups.json 檔案中的項目數量增加,尋找符合所有必要屬性的群組時,時間複雜度至少會呈線性增加。如果構件之間存在限制,更新工具可能需要聯結多個 artifact_groups.json 檔案才能進行選取,因此可能出現超線性情況。構件發布者可能需要逐出過舊的構件群組,以提升用戶端更新工具的效能。
選取大型產品後,下載構件的時間可能會相當長。這與現狀並無不同。相較於全域整合,這裡介紹的設計具有優勢,因為 fetch 工具一次只需要將一個產品的預先建構構件下載至任一整合存放區。在目前的全球整合中,所有已知產品的預先建構構件聯集都必須在 jiri update 期間下載。
隱私權注意事項
儲存在構件商店中的唯一新資料是 artifact_groups.json 檔案。構件商店的發布商有責任確保 artifact_groups.json 檔案中不會發布 PII。
測試
工具使用的程式庫 (例如,用於比對 artifact_spec.json 檔案和 artifact_groups.json 檔案中的屬性模式) 會透過單元測試進行測試。
如要以可執行檔的形式操作工具,整合測試會從本機保留的黃金檔案運作。
在端對端測試中,會有一個「Hello World」產品,位於自己的存放區中,持續執行機器,並監控失敗情形。
缺點、替代方案和未知事項
使用其他類型的構件商店
除了 TUF 之外,還有其他可用的構件商店。例如:
- CIPD
- 靜態 HTTPS 伺服器,
- GCS bucket,
- Git 存放區。
您可以在所有這些構件商店中,建立適當的結構,以內容位址的名稱找出構件,並在 artifact_groups.json 檔案中維護中繼資料,與上述提案實作中使用的 TUF 存放區相同。
每個版本的 TUF 存放區
這個設計的舊版也曾採用另一種替代方案,也就是為每個構件版本建立 TUF 存放區。upload 工具不會為版本的所有構件建立群組,而是建立新的 TUF 存放區來存放構件。知名查詢存放區包含記錄屬性的 artifact_groups.json 檔案。其中會包含每個構件群組的存放區名稱,而非群組名稱。
這個方法的優點是支援使用暫時性套件的產品,這類套件只會在首次使用時傳送至裝置。在產品組裝中,該存放區會做為套件來源納入產品,用於在執行階段解析套件網址,而非在發行版本存放區中納入套件。
由於目前沒有這類產品,因此這項設計的使用要求遭到拒絕。此外,雖然裝置和 TUF 基礎架構的軟體傳送機制是為這類用途而設計,但從未證實能以這種方式用於正式版,且預計會進一步演進,之後才有可能實現。因此,我們極力希望不要鎖定目前的軟體交付狀態。同樣地,我們認為 TUF 基礎架構無法妥善處理大量 TUF 存放區。
TUF 存放區 targets.json 中列出的所有構件
最初的構想是將所有構件 (尤其是所有 Fuchsia 套件) 列在 TUF 存放區的 targets.json 檔案中,而將構件分組到一個版本的目錄,則是實際包含 TUF 存放區目標的目錄。該資訊與 artifact_groups.json 中已記錄的資訊重複,且沒有任何用途,因此為了清楚起見,我們已捨棄該資訊,並避免對 targets.json 施加大小限制,而僅列於 targets.json 中的檔案則不受此限。
不明
目前仍有未解答的問題,與所呈現設計的可能擴充功能有關。
- 這個機制是否也適用於 Fuchsia SDK?Fuchsia SDK 是建立花瓣元件和樹外產品的必要構件,就像建立產品需要預先建構的構件一樣。您需要根據描述兩者的屬性,以非常類似的方式選取變體和版本。因此,問題在於花瓣建構程序是否應在
artifact_spec.json檔案中聲明使用 SDK,以及產品建構程序是否應在artifact_spec.json檔案中加入 Fuchsia SDK。 - 這項機制是否也適用於花瓣 SDK,也就是一個花瓣提供給其他花瓣的 SDK,例如 Flutter SDK?這並非啟用去中心化產品整合的必要條件,但可簡化產生的分散式建構程序。舉例來說,上傳工具可以檢查花瓣存放區鎖定檔案中擷取的 Flutter SDK 版本,找出上傳構件的正確 Flutter SDK 版本屬性值。
- 這個機制是否也可用於發布建構的產品?在工作站實作中,紫紅色工作站產品可能會發布至構件商店。上傳的產品稍後可用於差異組裝。
- 是否可使用說明機制,為產品建立過程中涉及的所有二進位構件,以遞移方式建立二進位透明度,回溯至產品中包含的預先建構構件、用於組裝產品的工具的預先建構構件、用於建立預先建構構件的工具等,依此類推。
說明文件
這份文件是初始說明文件。屆時會有相關工具和說明頁面。工作站存放區設定將做為藍圖和示範,供後續使用。
既有技術和參考資料
其他作業系統的產品整合通常來自來源樹狀結構,較少使用預先建構的項目,因此在存放區之間並行傳播這類預先建構項目的多個變體和版本時,需求較少。
建構系統會「選取」相容的依附元件「版本」,方法是在目前版本中重建依附元件,並使用目前套用的建構參數決定變數。這裡介紹的設計可以視為建構系統的泛化,可非同步運作和分散式運作。
相關文件
- 去中心化產品整合 Fuchsia 藍圖項目。
- 平台版本管理 RFC
- 獨立映像檔組裝工具 RFC
- 工作站樹狀結構外 RFC
- 樹狀結構外的 Bazel SDK RFC 草案
- 去中心化產品整合、構件選取規格 RFC 草案
- Product Assembly From Subassemblies RFC 草案
附錄
圖 4 - 全球整合圖例
