Flutter 裡的持續部署

透過 Flutter 持續交付的最佳實踐,確保您的應用程式交付給您的 Beta 版本測試人員並能夠頻繁予以驗證,而無需藉助手動工作流程。

CI/CD 選擇

有許多持續整合 (CI) 和持續交付 (CD) 的工具,幫助自動釋出你的應用。

內建 Flutter 的多合一 (All-in-one) 選擇:

使用 Fastlane 與現有工作流程整合

你可以透過下面的工具使用 fastlane:

這份指南展示瞭如何讓設定 fastlane 以及將其整合到現有應用的測試和持續整合 (CI) 工作流當中去。更多相關的內容,請參考上面這部分的內容。

fastlane

fastlane 是一個開源工具套件,幫助你自動的打包正式版以及部署你的應用。

本地設定

建議在遷移到基於雲計算的系統之前,先在本地測試其建構和部署流程。您還可以使用本地機器執行連續交付。

  1. 安裝 fastlane gem install fastlanebrew install fastlane。存取 fastlane docs 以獲得更多資訊。

  2. 建立一個名為 FLUTTER_ROOT 的環境變數,並將其設定為 Flutter SDK 的根目錄。(這是為 iOS 部署的指令碼所必需的。)

  3. 建立您的 Flutter 專案,準備就緒後,確保透過如下途徑建構專案:

    • Android flutter build appbundle;
    • iOS flutter build ipa.
  4. 初始化各平台的 fastlane 專案:

    • Android:在 [project]/android 目錄中,執行 fastlane init 命令。

    • iOS:在 [project]/ios 目錄下,執行 fastlane init 命令。

  5. 編輯 Appfile 以確保它有應用程式的基本資料配置:

    • Android 檢查在 [project]/android/fastlane/Appfile 檔案中的 package_name 是否匹配在 AndroidManifest.xml 中的套件名稱。

    • iOS 檢查在 [project]/ios/fastlane/Appfile 中的 app_identifier 是否匹配 Info.plist 檔案中的 bundle identifier。將相應的 apple_iditc_team_idteam_id 輸入進去。

  6. 設定應用商店的本地登入憑據。

    • Android 按照 Supply setup steps 文件操作,並且確保 fastlane supply init 成功同步了你在 Google Play 商店控制檯中的資料。 .json 檔案與密碼一樣重要,切勿將其公開在任何公共原始碼控制儲存庫。

    • iOS iTunes Connect 使用者名稱已經存在於您的 Appfileapple_id 欄位中,你需要將你的 iTunes 密碼設定到 FASTLANE_PASSWORD 這個環境變數裡。否則,上傳到 iTunes/TestFlight時會提示你。

  7. 設定程式碼簽名:

    • Android 參考文件 為應用簽名

    • iOS 在iOS上,當您準備使用 TestFlight 或 App Store 進行測試和部署時,使用分發證書而不是開發證書進行建立和簽名。

      • Apple Developer Account console 建立並下載一個分發證書。

      • 開啟 [project]/ios/Runner.xcworkspace/ 在你的專案設定裡選擇一個分發證書。

  8. 給每個不同的平台建立一個 Fastfile 指令碼。

    • Android 在 Android 上按照 fastlane Android beta deployment guide 指引操作。你可以簡單的編輯一下檔案,加一個名叫 upload_to_play_storelane。為了使用 flutter build 命令編譯 aab,要把 apk 引數設定為 ../build/app/outputs/bundle/release/app-release.aab

    • iOS 在 iOS 上,按照 fastlane iOS beta 部署指南 指引操作。你可以指定 archive 的路徑以避免重複建構。例如:

      build_app(
        skip_build_archive: true,
        archive_path: "../build/ios/archive/Runner.xcarchive",
      )
      upload_to_testflight
      

你現在已準備好在本地執行部署或將部署過程遷移到持續整合(CI)系統。

在本地執行部署

  1. 建構釋出模式的應用:

    • Android flutter build appbundle.
    • iOS flutter build ipa.
  2. 在每個平臺上執行 Fastfile 指令碼。

    • Android cd android then fastlane [name of the lane you created].
    • iOS cd ios then fastlane [name of the lane you created].

雲建構和部署設定

首先,按照“本地設定”中描述的本地設定部分,確保在遷移到 Travis 等雲系統之前,該過程有效。

需要考慮的主要事項是,由於雲實例是短暫且不可信的,因此你不能在伺服器上保留你的憑據,如 Play Store 服務帳戶 JSON 或 iTunes 分發證書。

持續整合 (CI) 系統通常支援加密的環境變數來儲存私有資料。你可以使用 --dart-define MY_VAR=MY_VALUE 在建構應用時傳遞環境變數。

採取預防措施,不要在測試指令碼中將這些變數值重新回顯到控制檯。 在合併之前,這些變數在拉取請求中也不可用,以確保惡意行為者無法建立列印這些金鑰的拉取請求。在接受和合並的 pull 請求中,請注意與這些金鑰。

  1. 暫時性登入憑據。

    • ![Android](https://flutter.tw/assets/images/docs/cd/android.png 在 Android 上:

      • Appfile 中刪除 json_key_file 並將其儲存在 CI 系統的加密變數裡。從 Fastfile 中直接讀取這些環境變數。

        upload_to_play_store(
          ...
          json_key_data: ENV['<variable name>']
        )
        
      • 序列化您的上傳金鑰(例如,使用 base64)並將其另存為加密環境變數。可以可以在安裝階段在 CI 系統上對其進行反序列化

        echo "$PLAY_STORE_UPLOAD_KEY" | base64 --decode > [path to your upload keystore]
        
    • iOS 在 iOS 上:

      • 將本地環境變數 FASTLANE_PASSWORD 轉而使用 CI 系統的加密的環境變數。

      • CI 系統需要有許可權拿到你的分發證書。建議使用fastlane 的 Match 系統在不同的機器上同步你的證書。

  2. 建議每次使用 Gemfile 而不是 gem install fastlane 以避免其在 CI 系統上使用的不確定性,以確保 fastlane 依賴關係在本地和雲計算機之間穩定且可重現。但是,此步驟是可選的。

    • [project]/android[project]/ios 資料夾中,建立一個 Gemfile 包含以下內容:

      source "https://rubygems.org"
      gem "fastlane"
      
    • 在兩個目錄中,執行 bundle update 並將兩者的 GemfileGemfile.lock 檔案納入原始碼管理。

    • 當你在本地執行的時候,請使用 bundle exec fastlane 而不是 fastlane

  3. 在你的儲存庫根目錄建立一個 CI 測試指令碼,例如: .travis.yml.cirrus.yml

    • 有關特定於 CI 的設定,請參見 fastlane CI 文件

    • 分開你的指令碼以便能在 Linux 和 macOS 兩個平台執行。

    • 在 CI 的設定階段,執行下列內容:

      • 透過執行 gem install bundler 確保 Bundler 可用。

      • [project]/android[project]/ios 目錄下分別執行 bundle install命令。

      • 確保 Flutter SDK 已經正確了設定在了 PATH 環境變數中。

      • 在 Android 平臺上,請確保已經設定正確的 ANDROID_SDK_ROOT 環境變數。

      • 在 iOS 平臺上,你需要為 Xcode 指定依賴 (比如: osx_image: xcode9.2)

    • 在 CI 任務的指令碼階段:

      • 根據平台的不同可以執行 flutter build appbundle 或者 flutter build ios --release --no-codesign

      • 然後執行 cd androidcd ios 命令。

      • 最後執行 bundle exec fastlane [name of the lane] 命令。

Xcode Cloud

Xcode Cloud 是一項為分發 Apple 平台的持續建構整合並交付,以及測試分發的服務。

需要準備的

自訂建構指令碼

Xcode Cloud 可以識別 自訂的建構指令碼 用於在特定階段執行額外的任務。同時它還包含了一系列 預定義的環境變數,例如用於你 clone 儲存庫地址的 $CI_WORKSPACE

Post-clone 指令碼

利用 post-clone 執行的自訂建構指令碼 Xcode Cloud 按照以下說明複製你的 Git 儲存庫:

ios/ci_scripts/ci_post_clone.sh 建立一個檔案,然後新增下面的內容。

#!/bin/sh

# The default execution directory of this script is the ci_scripts directory.
cd $CI_WORKSPACE # change working directory to the root of your cloned repo.

# Install Flutter using git.
git clone https://github.com/flutter/flutter.git --depth 1 -b stable $HOME/flutter
export PATH="$PATH:$HOME/flutter/bin"

# Install Flutter artifacts for iOS (--ios), or macOS (--macos) platforms.
flutter precache --ios

# Install Flutter dependencies.
flutter pub get

# Install CocoaPods using Homebrew.
HOMEBREW_NO_AUTO_UPDATE=1 # disable homebrew's automatic updates.
brew install cocoapods

# Install CocoaPods dependencies.
cd ios && pod install # run `pod install` in the `ios` directory.

exit 0

該檔案需要加入 git 儲存庫管理,並給予可執行許可權。

$ git add --chmod=+x ios/ci_scripts/ci_post_clone.sh

工作流配置

Xcode Cloud workflow 定義了你工作流觸發時 CI/CD 處理處理序的執行步驟。

要在 Xcode 中建立一個工作流,請參考以下步驟:

  1. 選擇 Product > Xcode Cloud > Create Workflow 以開啟 Create Workflow 選單。

  2. 選擇工作流需要作用的生產應用,然後點選 Next 按鈕。

  3. 下一步,選單將會展示一個 Xcode 提供的預設工作流的浮層,然後可以透過點選 Edit Workflow 按鈕進行客製。

變更分支

預設 Xcode 建議每次分支變更後都為你儲存庫的預設分支開始一個全新的建構。

對於你應用的 iOS 變體,你通常會希望 Xcode Cloud 在對你的 Flutter packages 修改了 lib\ 中的 Dart 或 ios\ 中的 iOS 原始檔目錄之後,觸發你的工作流。

這可以透過使用下列檔案和資料夾條件來實現:

Xcode Workflow Branch Changes

下次建構的建構版本數字

Xcode Cloud 對於新的工作流來說預設的建構版本數字是 1,然後在每次成功建構後遞增。如果你已經在一個已有應用中,使用了一個更高的建構版本數字,你需要配置 Xcode Cloud 使用正確的建構版本數字,只需要簡單透過指定 Next Build Number 用於迭代即可。

你可以在 設定 Xcode Cloud 建構下一次的建構版本數字 檢視更多資訊。