YiBi Dev Docs
架構決策 (ADR)

固定 Flutter SDK 版本於 CI 與本機 toolchain(停用 stable channel 浮動)

Context

既有設計

本 monorepo 含 Flutter mobile(mobile/)。CI 透過 subosito/flutter-action@v2 取得 Flutter SDK,原本所有 step 僅指定 channel: stable未指定版本

- uses: subosito/flutter-action@v2
  with:
    channel: stable

本機開發則由 asdf 透過 .tool-versions 管理(與 bunterraform 同一機制)。

觸發

channel: stable 不指定版本時,CI 每次執行會抓取當下最新的 stable 版本。 這造成兩個問題:

  1. 不可重現:不同時間點的 CI run 可能跑在不同 Flutter 版本上;上游發佈新 stable 後,原本綠燈的 main 可能在下一次 run 無預警變紅,且無 code 變更可對應。
  2. 本機與 CI 不一致.tool-versions 釘住的版本與 CI 浮動版本可能不同, 開發者本機通過、CI 失敗(或反之),難以除錯。

CI 是 merge gate,浮動版本等於把「工具鏈版本」這個變因留在不受控狀態。

Decision

結論:Flutter SDK 版本在 CI 與本機 toolchain 兩側都顯式釘住單一版本, 升級改為經 review 的刻意變更,而非隱性浮動。

實作分兩個 PR(見文末 Links):

  • PR #546(釘版)
    • CI:保留 channel: stable,並在所有 subosito/flutter-action@v2 step 加上 flutter-version 釘住 3.44.0——共 5 處:.github/workflows/ci.yml(2)、 .github/workflows/cd-mobile.yml(2)、.github/workflows/flutter-e2e.yml(1)。
    • 本機.tool-versionsflutter 3.44.0-stable(asdf)。
    • 文件ONBOARDING.md 的 Flutter SDK 版本同步標註為釘住版本。
  • PR #547(後續防護):#546 merge 後由 mob review(Claude + Codex + Gemini)共識補上:
    1. .tool-versions 變更觸發 Flutter CI——原本 Flutter CI 的 paths-filter 只認 mobile/**,純 .tool-versions 的 SDK bump 不會觸發任何 Flutter check, 釘版形同虛設;#547 將 .tool-versions 納入觸發路徑。
    2. 版本值加單引號flutter-version: '3.44.0'),避免 YAML 將其解讀為 float 等型別歧義。

channel: stableflutter-version 並存:action 會在 stable channel 內解析到 指定的精確版本,因此 channel 欄位保留不影響釘版效果。

升級流程:bump 版本時,必須同時更新 CI 5 處 + .tool-versions + ONBOARDING.md;因 #547 已將 .tool-versions 納入 Flutter CI 觸發路徑,SDK bump 本身即會觸發 Flutter check(含 mobile P0 critical path),須綠燈後才合併。

Alternatives Considered

  • 方案 A:維持 channel: stable 浮動(不指定版本) — 考慮過,因為 不可重現 + 本機/CI 版本漂移,且上游新 stable 會無預警打斷 main 而拒絕。
  • 方案 B:只釘 .tool-versions,CI 不釘 — 考慮過,因為 CI 仍浮動、 且 CI 才是 merge gate,本機釘版無法阻止 CI 因版本漂移失敗,故不足。
  • 方案 C:導入 FVM(Flutter Version Management) — 考慮過,因為 會多一層 版本管理工具,而 asdf + .tool-versions 已是本 repo 既有 toolchain 標準 (bun/terraform 同機制),為維持單一機制而不採用。

Consequences

  • CI build 可重現;同一 Flutter 版本貫穿所有 run 與本機。
  • 消除「上游發佈新 stable → 無 code 變更卻打斷 main」的浮動風險。
  • 本機與 CI 版本對齊(.tool-versions ↔ workflows)。

壞 / 代償

  • 升級需在多處手動 bump(CI 5 處 + .tool-versions + ONBOARDING.md), 存在「只改部分、版本不一致」的風險,須在同一 PR 內全部對齊。
  • 不再自動取得最新 stable 的修復/安全更新,需靠刻意 bump 才會跟進。
  • 需要一個升級紀律:bump 時同步全部位置並跑 mobile P0 測試。

中性

  • channel: stable 保留,與 flutter-version 並存(action 於 stable channel 內 解析精確版本)。
  • 3.44.0 為目前釘住的 baseline;後續版本演進以 git tag / PR 追蹤。
  • PR #546 — chore(ci): pin Flutter SDK to 3.44.0 across CI and .tool-versions(釘版,已 merged 2026-06-18)
  • PR #547 — ci: validate Flutter SDK on .tool-versions changes + quote versions(後續防護:.tool-versions 變更觸發 Flutter CI + 版本值加引號,已 merged 2026-06-18)

On this page