RFC-0124 - 分散式產品整合:構件說明與傳播

RFC-0124:去中心化產品整合:構件說明和傳播
狀態已接受
區域
  • 一般
說明

用於描述及散發非集中式產品整合作業的構件機制。

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

摘要

本 RFC 說明一種機制,可從 Fuchsia 來源樹或花瓣存放區建立來源或預先建構的構件,用於組合 Fuchsia

這個機制包含兩個重要層面:

  1. 使用適當的元資料,為構件提供說明,以便選取相容或其他理想的版本和變化版本,並納入要組合的產品。
  2. 傳播構件,以便在來源存放區 (構件來源) 和用於構件的整合存放區,同時識別、參照及存取構件。

提振精神

去中心化產品整合路線圖文件所述,建議在 Fuchsia 來源樹狀結構之外組合產品。為達成此目標,您必須在 Fuchsia 來源樹狀結構之外執行獨立映像檔組合工具,並為這些工具提供必要的來源或預先建構的構件。Fuchsia 來源樹狀結構會提供 Zircon (Fuchsia 核心) 和系統套件等其他構件。各種 Petal 存放區會提供額外元件的套件,例如產品專屬元件和執行程式。

Fuchsia 來源樹狀結構構件會以規律的版本週期產生。同時,Fuchsia SDK 的版本也會產生,並定期由花瓣存放區匯入,然後在花瓣存放區的版本節奏中產生自己的 Fuchsia 構件。

一般來說,花瓣儲存庫的發布週期與 Fuchsia 來源樹狀結構的發布週期不一致,且版本的 ID 也不同。花瓣可以選擇將發布週期與 Fuchsia 保持一致,例如為每個 Fuchsia SDK 版本製作一個版本。

每個這類成果版本也可能會以不同的變化版本產生,例如各種處理器架構的可執行檔、偵錯與最佳化變化版本、以「穩定」與「最新」標籤指定的變化版本 (用於區分主幹版本與穩定分支版本),或是啟用或停用的建構時間功能的變化版本。

為了在與 Fuchsia 來源樹狀結構分開的整合存放區中,從這類構件組合產品,必須將構件提供給整合存放區。此外,產品整合所需的構件必須針對產品的每個版本和子類,選取相應的構件版本和子類。

目前的產品整合程序稱為「全域整合」。來自花瓣存放區的預先建構構件會在名為滾動式更新的程序中匯入至 Fuchsia 來源樹狀結構。接著,系統會將 Fuchsia 產品組合為最終建構產品,這些產品來自最新來源修訂版本的 Fuchsia 來源樹狀結構中的所有構件,以及已達到整合存放區的固定版本中 petal 存放區中的預先建構套件。這項程序如圖 1 所示。

圖 1 - 全球整合程序 (圖例) 目前系統中所有合作部分的關係

這個程序有幾個缺點:

  • 產品組合設定會保留在 Fuchsia 來源樹狀結構中,而非由
  • Fuchsia 系統的版本一律會領先任何花瓣構件所建構的 Fuchsia SDK 版本,因為 Fuchsia 系統是根據 Fuchsia 來源樹狀結構的最新來源修訂版本建構,但花瓣構件的 SDK 是根據較早的修訂版本建構。
  • 如果不同花瓣的構件之間有版本相容性要求 (例如 Flutter 執行元件和以 AOT 編譯的 Flutter 應用程式),則必須在同一個 Roller 中特別將這些構件一起推出,才能維護這些構件。
  • 即使花瓣構件由產品擁有者控管,用於產品整合的版本仍不受控管,因為讓新版本構件可供產品整合的滾動式程序會與所有其他花瓣構件的所有其他滾動器協調,且可能因任何其他產品的整合測試失敗而遭到封鎖。

建議的去中心化產品整合程序可改善這些缺點,因為這會直接導致在 Fuchsia 存放區外啟用產品組裝:

  • 產品組合設定會保留在每項產品的個別整合存放區,可由產品擁有者控制。
  • 您可以選取與用於建構花瓣構件所用的 Fuchsia SDK 相容的 Fuchsia 構件,以便在產品的所有構件之間達成 ABI 相容性。舉例來說,類似於 RFC-0002 中規定的 ABI 修訂版本,以及對應於必要的 6 週 ABI 相容性時間窗口,會由 Fuchsia 發布版本號碼的第一個元件表示,每次建立 Fuchsia 發布分支時,這個元件都會遞增。因此,您可以將產品中的所有構件與 SDK 建構時使用的 SDK 的 Fuchsia 發布版本號碼相等的第一個元件對齊。
  • 您可以直接選取不同花瓣存放區的構件版本,以便滿足相互相容性要求,並可根據直接指定的限制條件升級至下一個版本,而無需為這兩個構件設定專屬的輪替器。舉例來說,您可以直接選取 Flutter 應用程式和對應的 Flutter 執行元件,以便取得相同的 Flutter 和 Dart 發布版本號碼。
  • 產品可依據自身的發布週期,選取所有貢獻構件版本和變化版本,而不會阻止其他產品也選取該版本。

利害關係人

協助人員:abarth@google.com

審查者:aaronwood@google.com (組裝)、etryzelaar@google.com (SWD)、wittrock@google.com (SWD)、atyfto@google.com (Fuchsia 建構基礎架構)、marvinpaul@google.com (TUF 伺服器基礎架構)、jsankey@google.com (安全性)、enoharemaien@google.com (安全性與隱私權)、schilit@google.com (相關 RFC 作者)。

諮詢對象:軟體提交團隊、受管理作業系統團隊和基礎架構團隊成員。

社會化:除了與諮詢團隊討論外,我們也將本 RFC 草稿傳送至 FEC 討論郵寄清單,徵求意見。

設計

在介紹設計總覽之前,我們會先介紹或說明一些術語和概念。

術語

在下文段落中,粗體字詞的意思會在周圍文字中說明。

Fuchsia 來源樹狀結構包含多個不同的 Git 存放區,這些存放區會根據儲存在名為 integration.git 的 Git 存放區中的設定,由名為 jiri 的工具一起設定為一個來源樹狀結構。這些 Git 存放區中最重要的是 fuchsia.git,但還有許多其他存放區,包括第三方存放區。jiri 設定也能控制是否將預先建構的構件納入來源樹狀結構的專屬部分。預先建構的構件本身會儲存在名為 CIPD 的儲存空間服務中,並受修訂版本控制,而描述 CIPD 中預先建構的構件位置和修訂版本的 jiri 設定,則會受 integration.git 存放區中的 Git 修訂版本控制。

定期執行的建構工作稱為 Roller,會嘗試更新 Fuchsia 來源樹狀結構中所含預先建構的構件版本。如果 Fuchsia 樹狀結構的所有所需建構產品都能使用更新後的構件版本進行建構和測試,則會提交 Fuchsia 樹狀結構的變更,而更新後的構件版本現在則是已固定的版本。不同的預先建構成果可以有不同的滾動條。

在現況中,Fuchsia 來源樹狀圖同時扮演兩種角色:Fuchsia 產品中使用的許多構件來源集區,以及整合集區,其中每個 Fuchsia 產品都是由其零件組合而成。

Artifact 是指產品組裝過程中使用的任何成分。這類構件會從來源存放區取得,可以直接做為來源項目之一,也可以做為在存放區中執行建構程序後取得的建構產品。這類構件大多是預先建構的 Fuchsia 套件,但也包含 Zircon、Fuchsia 核心,不久後可能還會包含子組裝規格檔案。Zircon 核心和預先建構的套件是預先建構的構件;子組件規格檔案則是來源構件。

從一個來源存放區取得的構件最終會發布構件商店。這類版本可以手動發布,也可以在預定時間間隔內自動發布。無論採用哪種方式,產生的構件都會發布至來源存放區的專屬構件商店。只要是可從來源存放區以外的地方找到構件的地方,都可以是構件儲存庫,無須參照來源存放區,更不用說執行建構程序。因此,Artifact Store 可以是 CIPD 目錄、GCS 值區或 TUF 存放區。就這裡設計的程序而言,特定類型的構件儲存庫並非必要。

TUF 存放區可用於將軟體提交至 Fuchsia 裝置,將新建的套件提交至開發中的 Fuchsia 裝置或模擬器,以及將 OTA 更新提交至實際使用的 Fuchsia 裝置。在 Fuchsia 中使用 TUF 的具體方式,可在內容位址儲存服務之上,特別適合用於儲存 Fuchsia 套件。由於許多構件都是 Fuchsia 套件,因此這個設計會偏好使用 TUF 存放區做為構件儲存庫。

屬性是用來描述構件 (例如版本和變化版本) 的鍵/值屬性。鍵會描述變化程度,而值則是沿著該維度中遺跡所在的位置。屬性會統一描述構件的版本和變化版本。在多數情況下,您不需要區分描述版本的屬性和描述變數的屬性。構件發布者可以指定下列屬性:

  • CPU 架構變化版本:x64arm64
  • debugoptimized 編譯變化版本。
  • 建構構件的來源原始碼存放區提交版本。
  • 建構參數,用於建構構件。
  • 建構產物所使用的 Fuchsia SDK 版本。
  • 已建構的構件語意版本。例如 Chromium 發布版本 (例如 M88.xxx),或是 Cast 發布版本 (例如 1.56.xxx)。
  • 實作後,Fuchsia 系統 Artifact 的 RFC-0002 規定的 API 級別和 ABI 修訂版本。
  • 花瓣提供的 API 級別或 SDK 版本,雖然不屬於 RFC-0002 的範疇,但與系統 ABI 同樣重要。例如,Flutter 應用程式建構時使用的 Flutter SDK 發布版本。

轉移屬性:部分屬性會描述構件檔案的轉移屬性,因為這些屬性與構件檔案所建構的輸入內容屬性相關。舉例來說,Fuchsia SDK 版本或 Flutter 版本其實是先行構件用來建構所述構件的屬性。這類傳遞性質的擴展範圍預期會更廣泛。因此,屬性值可為物件,並依序遞迴地包含鍵/值組合。

依附元件屬性:成果的依附元件 (包括版本和變化版本) 也可以用屬性表示。不過,Fuchsia 套件是密封的,因此已包含其依附元件。因此,依附元件通常不會經常出現在 Fuchsia 構件屬性中。

現況

在目前的全球整合程序中,如圖 2 所示,petal 建構程序會使用 CIPD 目錄做為構件儲存庫。構件儲存庫會在路徑名稱下保留構件 (在 CIPD 中稱為「package」,與 Fuchsia 套件沒有直接關聯)。CIPD 支援在「套件」的相同路徑名稱下儲存多個「例項」,並將「標記」和「參照」附加至例項。子類別中繼資料會在已儲存構件的路徑名稱元件中編碼。版本中繼資料會在 CIPD 套件例項的標記和參照中編碼。產品建構程序會透過滾動取得固定版本的構件,並一律從固定版本的花瓣構件建構產品。

圖 2 - 目前的系統結構 目前系統中所有合作部分的關係

透過構件儲存庫傳播擴充中繼資料

這裡提出的設計會變更構件儲存庫的結構,以便保留已發布的構件中繼資料屬性。產品接著可根據屬性值指定的條件,選取合適的構件。

這項設計涉及三個額外的設定檔,以及三個用於操作設定檔以與構件儲存庫互動的工具。檔案為 artifact_groups.json,儲存在構件商店中;artifact_spec.jsonartifact_lock.json 則儲存在產品整合存放區中。如圖 3 所示,uploadupdatefetch 工具會對檔案和構件執行操作,如下所示:

  1. 每個新版本的一系列構件,從 petal 或 Fuchsia 建構程序建立,會在與來源存放區相關聯的構件儲存庫中建立新的構件群組。已發布的構件屬性會記錄在 artifact_groups.json 檔案中,該檔案也會保留在構件儲存庫中。
    • Petal 建構程序會使用 upload 工具,將新發布的構件發布至構件存放區,並更新 artifact_groups.json 檔案。
  2. 在產品整合存放區中,artifact_spec.json 檔案會保留清單,指出要從哪些構件儲存庫取得整合存放區中產品組件的構件,以及要使用哪些屬性。
    • update 工具可用於選取實際用於組件的構件集,方法是使用整合存放區中的 artifact_spec.json 檔案,以及 artifact_spec.json 檔案中列出的所有構件儲存庫中的 artifact_groups.json 檔案。
  3. update 工具所選取的成果集會儲存在 artifact_lock.json 檔案中。
    • fetch 工具會下載 artifact_lock.json 檔案中提及的所有構件,以便將這些構件提供給整合存放區中的產品建構程序。

這些工具與建構規則的執行方式相關,取決於產品整合存放區中使用的特定建構系統。詳情請參閱「實作」一節。

這些工具可讓整合存放區中有多個 artifact_spec.jsonartifact_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 儲存庫中 Artifact 的儲存位置。相反地,所有構件都會儲存在其內容位址下,而 artifact_groups.json 中每個構件的內容位址都會記錄為 merkle 屬性。

使用的內容位址是構件立即內容的 Fuchsia merkle 根。部分構件 (特別是 Fuchsia 套件) 會以進一步的儲存空間元件 (稱為「blob」) 表示,這些元件會間接包含在構件的直接內容中。這些額外元件會儲存在其內容位址下,但不會在 artifact_groups.json 中明確提及。

唯一性不變量

在 Artifact Store 中,您必須維護一些不重複的變異值。這些不變量可確保透過參照構件名稱和屬性,明確選取構件:

  1. 在整個記錄期間,群組名稱在構件儲存庫中不得重複。
  2. 每個群組中的成果名稱不得重複。
  3. 在目前的構件儲存庫中,同一個群組中所有同名構件的屬性不得重複。

當新的構件群組新增至構件儲存庫時,這些不變性特徵會由 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 檔案,以下稱為「規格檔案」。這個檔案會列出產品在整合存放區中組合所需的構件、從哪些構件商店取得這些構件,以及構件屬性的模式和限制。也會說明構件儲存庫的類型,而且一個規格檔案中可以同時存在多種不同類型的構件儲存庫。

具體來說,預先建構的構件可儲存在整合存放區本身,並可在規格檔案中參照來自「local」類型構件存放區的構件。

整合存放區中的產品建構程序會使用 update 工具,比對規格檔案中提及的所有構件商店中的 artifact_groups.json 檔案,並計算要使用的特定構件變化版本和版本。這組資訊會記錄在 artifact_lock.json 檔案中。這個檔案應當做為存放區中的來源檔案提交。

fetch 工具會讀取 artifact_lock.json 檔案,並將所有構件下載至整合存放區。這些構件並非要以來源檔案的形式提交至存放區。不過,系統會在 artifact_lock.json 檔案中,透過從 artifact_groups.json 檔案擷取的內容位址來識別這些構件。這可確保 artifact_lock.json 的已提交內容能完全決定提供給建構作業的構件內容,進而確保產品組合建構作業在 artifact_lock.json 檔案中選取的構件是密封且可重現的。

實作

我們首先會實作這裡提出的設計,將工作站產品整合移至單獨的存放區

另一個 RFC 說明瞭 artifact_spec.json 的必要詳細資料,以及如何針對 artifact_groups.json 檔案處理 artifact_spec.json,以產生 artifact_lock.json 檔案。

遷移現有花瓣和產品

只要 Fuchsia 來源樹狀結構仍需要使用 petal 預先建構項目 (從 integration.git 設定),就必須將這些項目上傳至 CIPD,供 Fuchsia 來源樹狀結構中的 gn 建構規則使用,並上傳至由樹狀結構外產品使用的構件儲存庫。最終,Fuchsia 來源樹狀結構中將不再需要某些 petal 預先建構項目,因此可以停止將其上傳至 CIPD。

我們無意使用 jiri 取代設定 Fuchsia 來源樹狀結構的機制,因為所有 Fuchsia 平台構件、SDK 和部分產品仍會繼續從 Fuchsia 來源樹狀結構建構。

構件存放區

工作站及其花瓣的實作項目會使用 TUF 存放區做為構件儲存空間。TUF 存放區的 targets.json 檔案中,只有 artifact_groups.json 檔案的項目。構件本身會儲存在由 Fuchsia 使用的 TUF 伺服器基礎架構維護的內容位址 blob 儲存庫中,並在 artifact_groups.json 檔案中記錄其對應的 blob 位址。

此外,構件也可以列在 targets.json 中的目錄和構件名稱下方,但這個設計中並未要求這麼做。(這只是為了完整呈現歷史資料,因為過去如果有人需要 targets.json 項目,就會這樣做。請參閱下方的替代方案一節)。

Fuchsia 套件結構依附元件

這裡提出的三個工具可與構件集合存放區互動 (上傳、更新、擷取),並在 Fuchsia 套件上運作,因此會對 Fuchsia 套件的結構做出假設。具體來說,我們假設 Fuchsia 套件包含 meta.far blob,其中包含內容位址 (以 merkle 根表示),以及屬於該套件的其他 blob。系統會使用 Fuchsia SDK 提供的工具取得 meta.far 中參照的 blob 清單,因此構件儲存工具 (上傳、更新、擷取) 不依賴 meta.far 的內部結構。

工具與建構規則的關係

uploadupdatefetch 工具與執行建構規則的關係,取決於來源存放區和產品整合存放區中的特定建構系統,以及建構作業執行的基礎架構。

建構系統完成建構作業後,系統會執行 upload 工具。

通常,update 工具應在建構規則之外使用,並在建構作業執行前使用。

fetch 工具可在執行建構規則之前使用,如果建構系統支援,也可以在建構系統執行時使用。對於工作站,bazel 會用作建構系統,可在所謂的「工作區規則」中設定輸入檔案集。

工具可執行檔的名稱

工具 uploadupdatefetch 最終可能會以其他名稱實作,而非這項設計中使用的概念名稱。具體來說,這些工具可做為 ffx 工具的外掛程式導入,或做為 bazel 建構規則產生的工具。初始原型會將這些項目實作為名為 artifact_upload.pyartifact_update.pyartifact_fetch.py 的 Python 指令碼。

檔案語法

以下 JSON 結構定義會提供 artifact_groups.json 檔案的語法。artifact_spec.jsonartifact_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.jsonartifact_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 都是物件,格式如下:

{
  "name": NAME,
  "merkle": MERKLE,
  "type": TYPE,
  "attributes": ATTRIBUTES
},

名稱

包含此構件名稱的字串。

MERKLE

資源的 Merkle 根目錄字串。

類型

包含此構件類型的字串。如果 TYPE"package",則由其梅克爾根目錄參照的 Blob 中的這個構件,就是 Fuchsia 套件的 meta.far,而 meta.far 中間接參照的 Blob 一律會與 meta.far Blob 一併處理。否則,構件只包含已列出 Merkle 的單一 Blob。

屬性

與上述定義的 ATTRIBUTES 類似的物件。這是定義構件專屬屬性的地方。

安全性考量

本 RFC 中的設計不會變更現有參與者之間的信任模式。這個機制只會變更儲存空間結構,不會變更使用構件儲存庫的發動者之間,或發動者與構件儲存庫之間的信任關係。

信任模式

如同目前使用 CIPD 做為構件存放區的現況,產品建構程序需要信任構件存放區。這項信任目前是根據存放區所應用的存取控制和驗證機制,以及存放區在將構件提供給存放區時,所依賴的 petal 和 Fuchsia 建構程序,來決定環境。存放區會解析已設定的存放區名稱,以便存取正確的存放區。

建立更多構件儲存庫和產品整合存放區後,就需要評估這些項目的信任基礎,並相應評估組合產品的可信度。

日後,我們可能會建立額外的機制,以便在目前使用的機制之上運作,例如驗證簽章 (例如 TUF 存放區中的簽章)。這裡設計的機制可支援相關資訊的傳播,以便評估可信度,但這類資訊的建立方式是互相獨立的。

特別針對 TUF 簽章,請務必注意,這類簽章只會提供證據,證明代管構件的存放區可信。這項資訊本身並不能構成評估從中取得的構件可信度的完整依據,因為這還取決於簽署金鑰的控管方式、產生構件的建構程序的可信度,以及建構程序用來做為輸入內容的傳遞來源和工具的可信度。就目前用於 Fuchsia 產品的 TUF 實作而言,它會為上傳至維護存放區的任何構件簽署,並且取決於 ACL 的完整性,以及讓用戶端存取該服務的驗證機制。

多個花瓣建構程序發布至相同的構件儲存庫

建議發布來源存放區不要共用構件儲存庫,這樣無論信任關係如何建立,都不會與伺服器共用信任關係。舉例來說,在實作 TUF 時,發布者不必分享簽署金鑰。

另外,多個花瓣式建構程序發布至相同的構件儲存庫時,也可能會產生妥協。舉例來說,某個發布者可能會覆寫其他發布者發布的構件。但這超出本 RFC 的範圍,因為在本 RFC 中,所有發布至構件儲存庫的 petal 建構程序都是由同一機構運作,因此可以妥善協調。如果要將這項功能擴展至多個機構,就需要設計不同的協調模型。

成效

隨著 artifact_groups.json 檔案中的項目數量增加,找到符合所有必要屬性的群組所需的時間複雜度至少會以線性方式增加。如果各個構件之間有限制條件,則可能會超線性,因為更新工具需要彙整多個 artifact_groups.json 檔案才能進行選取。構件發布者可能需要移除過舊的構件群組,以便改善用戶端更新工具的效能。

對於大型產品而言,一旦選取了構件,下載時間可能會相當長。這與現況並無二致。與全域整合相比,這裡提供的設計具有以下優點:fetch 工具只需將單一產品的預先建構構件下載至任何一個整合存放區。在目前的全域整合作業中,所有已知產品的預先建構構件組合,都必須在 jiri update 期間下載。

隱私權注意事項

唯一儲存在構件儲存庫中的新資料是 artifact_groups.json 檔案。至於是否要將 PII 發布至 artifact_groups.json 檔案,則由產物儲存庫的發布者自行決定。

測試

工具使用的程式庫 (例如用於比對 artifact_spec.json 檔案中的屬性模式與 artifact_groups.json 檔案) 會由單元測試進行測試。

針對以可執行檔案運作的工具,將會從本機儲存的黃金檔案執行整合測試。

針對端對端測試,專屬的存放區會包含「Hello World」產品,持續執行機制,並監控是否發生錯誤。

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

使用其他類型的構件儲存庫

除了 TUF 之外,您還可以使用其他構件儲存庫。例如:

  • CIPD,
  • 靜態 HTTPS 伺服器
  • GCS 值區
  • Git 存放區。

您可以在所有構件商店中建立適當的結構,以便在其內容位址下方找到構件,並在 artifact_groups.json 檔案中維護中繼資料,這與上述實作中使用的 TUN 存放區相同。

每個版本的 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?這並非啟用去中心化產品整合功能的必要條件,但可簡化後續的散發建構程序。舉例來說,上傳工具可以檢查 petal 存放區的鎖定檔案中擷取的 Flutter SDK 版本,進而找出上傳構件正確的 Flutter SDK 版本屬性值。
  • 這個機制是否也能用於發布已建構的產品?在工作站實作中,fuchsia 工作站產品可發布至構件存放區。這個上傳的產品日後可用於差異組合。
  • 說明機制是否可用於對產品建立作業中涉及的所有二進位檔成果建立二進位檔透明度,並回溯至產品中包含的預先建構成果、用於組合產品的工具的預先建構成果,以及用於建立預先建構成果的工具等。

說明文件

這份文件可做為初始文件。我們會提供工具,並附上說明頁面。工作站存放區設定可做為藍圖和示範,供日後使用。

既有技術與參考資料

其他作業系統的產品整合作業通常會從源樹開始,因為這類作業樹的預先建構項目使用較少,因此在儲存庫之間同時散布多個變化版本和預先建構項目版本的需求也較少。

建構系統「選取」相依項目的「版本」,只需在目前版本中重新建構相依項目,並在由目前套用建構參數決定的變化版本中執行此操作。這裡提供的設計可視為建構系統的泛用化,可用於非同步和分散式作業。

附錄

圖 4 - 全球整合圖的圖例 全球整合圖表的說明