iOS App 環境管理 : 靈活運用 Xcode Scheme、GitLab 和 Fastlane 設置不同的開發環境


真正產品化的 App,通常都有不同的環境與配置,包括環境資訊與後端不同環境的位置,上線後測試功能分流,一般實驗時可以很容易上手 CI/CD,但在實戰中可能需要更加複雜且靈活的設置。讓我們來看看,這些配置在實戰中是甚麼樣子!你可以在這裡參考原始碼。

在專案準備中,我們使用 GitLab 來實作。我們透過 GitLab CI/CD,完成產品 App 中的 CI/CD Pipeline 流水線的建置,然後建立一個新的 App 當作我們產品的標的(即模擬實戰中正在開發產品),並且分出各個環境來代表實戰中的項目環境。同時,配置 fastlane 在我們將程式碼推送到 GitLab 執行,它會幫我們在不同環境中執行各個事項,比如建置、打包、根據環境推送到不同的 App Store 項目中等等。後面,我們還會提供更進階的配置,比如 firebase 要怎麼納入我們的環境管理中。好,讓我們開始吧!

專案準備

首先,我們要建立好 GitLab 與 GitLab Runner,並新增一個 Xcode 專案,當作我們的產品標的。

建立 GitLab 專案與 Runner

gitlab-1

讓我們先在 GitLab 建立一個新專案,然後設定好 GitLab-CI Runner。這邊就不再贅述步驟,如果不熟悉的話,你可以參考這篇文章:GitLab 初學者指南: 輕鬆為 iOS 專案設定持續集成(CI/CD)

建立新的 iOS 專案

接下來,讓我們這樣建立一個新的 iOS 專案當作範例。

ios-project-1

預覽一下我們的新專案:

ios-project-2

配置環境

現在,我們要模擬一個產品中,有很多種環境。我們會先定義環境,再透過環境定義抽換各種變數。

讓我們加入以下環境:

  1. Debug
  2. Staging
  3. Release

按下 New Scheme:

App-環境管理-1

填入我們三個 Scheme 的名稱:

App-環境管理-2

這邊有個小伏筆,我故意把 Staging 打成 Stating,後面會詳述如何更正。

新增 Config

現在,讓我們建立 Config 資料夾:

config-1

然後,新增 Config 檔案:

config-2

我們一樣需要三個檔案:

  1. Debug.xcconfig
  2. Staging.xcconfig
  3. Release.xcconfig

然後,我們綁定 Config:

config-3

完成後,成果應該像這樣:

config-4

填入與設置變數

下一步,我們會模擬不同環境,有不同的 API 位置來作配置。我們會用網址來代表不同環境的後端 API 位置:

  • Debug.xcconfig
  • Staging.xcconfig
  • Release.xcconfig

預覽一下完成後的結果:

App-環境管理-3

修改 Info.plist

然後,我們如下修改 Info.plist:

建立 ServicesURL

下一步,我們要這樣建立 ServicesURL:

然後,讓我們的畫面讀取這個數值:

ServicesURL-1

最後,讓我們綁定 Scheme 並看看效果:

  • Debug 模式下
App-環境管理-4
  • Staging 模式下
App-環境管理-5
  • Release 模式下
App-環境管理-6

太棒了,我們已經成功的切換環境變數配置!最後,讓我們把成果推到剛建立好的 GitLab 遠端上:

push-to-gitlab-1

確認是否真的推上了:

push-to-gitlab-2

配置 Fastlane 與 Gitlab CI

接下來,我們需要配置好 Fastlane 與 Gitlab CI,讓我們的建置、配置、測試、部署完全自動化!

配置 Fastlane

首先,讓我們如此初始化 Fastlane:

Fastlane-configuration-1

然後,我們會以兩個文件來配置 Fastlane:

  • Fastfile
  • Appfile(這邊要記得換成自己的資訊)

然後,我們要初始化 cocoapods:

pod-init

如此編輯 Podfile,並且安裝

pod-install

讓我們重新修改 Xcode 配置:

xcode-configuration

然後新增檔案 .gitlab-ci.yml

gitlab-file

我們把 Stages 分為三個項目,填入以下程式碼:

  1. unit_tests 代表跑測試
    1. develop 代表 Staging 環境部署,並且 Release to Testflight
  2. master 代表 Release 環境部署,並且 Release to Testflight

完成了!接下來,我們想把這個成果展示在 Testflight 中,所以我們需要先配置一個 AppStore 項目。

配置 AppStore

讓我們到 AppStore 如此新增一個 App:

AppStore-1

完成後,App 應該會像這樣:

AppStore-2

測試 Fastlane

我們努力了那麼久,現在是時候測試一下成果了!

先在本地測試一下 fastlane 指令,如果遇到憑證問題,可以先到 Xcode 裡面設定好。

test-fastlane

記得在 Gemfile 加入 cocoapods

add-cocoapods

情境:環境配置錯了怎麼改

接下來讓我們模擬看看,如果在過程中,環境資訊配置錯誤了,該怎麼處理?

讓我們直接建立一個 Config Staging.xcconfig,直接更換配置就可以了,另外記得 Scheme 也要更換:

App-環境管理-7

然後確認看看:

App-環境管理-8

最後讓我們再跑一次 fastlane beta

run-fastlane

大功告成,我們再也不怕環境配置輸入錯誤而措手不及了!

測試 Gitlab CI

接下來讓我們推送到 Gitlab,測試與查看 Gitlab CI 的效果吧!

App-環境管理-9

在推送的同時,CI 也在執行中:

App-環境管理-10

太棒了,我們的 Gitlab CI 執行成功了!

App-環境管理-11

檢驗成果:Testflight

現在是收割的時刻了!接下來,我們需要到 Testflight 上查看,我們部署出去的 App 是不是真的可以使用 Testflight 提供測試。

先來檢查一下 Testflight 上有沒有檔案吧:

testflight-1

我們完成了!!

目前,我們把實戰中最基礎的配置部分都完成了!接下來,讓我們看看如何透過不同的分支,打包與部署出不同環境的 App 吧!

進階:不同分支的App Release

接下來,我們會示範使用分支來打包與部署不同環境的 App:

  1. 透過 Develop 分支 -> 推送 Staging 環境
  2. 透過 Master 分支 -> 推送 Release 環境
App-環境管理-9

可以看到我們的 CI 檔案中已經設置好應有的分支,再來只要推送就好了!

App-環境管理-10

嘩,我們成功讓不同分支可以讀到不同的環境配置了!

接下來,讓我們再更近一步,將不同環境的 App 部署到不同的 App Store 項目中,使得我們可以在正式與測試環境中很自由的使用與測試吧!

進階:把環境分到不同的 App 中

首先,讓我們再建立一個 AppStore App:

AppStore-3

然後,分別在 Config 檔案中加入變數:

App-環境管理-11
App-環境管理-12
App-環境管理-13

這邊有一個要特別注意的點,也是常常會出現的坑:就是要記得修改project.pbxproj內的程式碼:

App-環境管理-14
App-環境管理-15

最後,我們修改一下 Appfile:

App-環境管理-16

完成後,讓我們測試一下,看看替換有沒有成功:

App-環境管理-17
App-環境管理-18

然後,我們回到 AppStore 查看,確定 Deploy 成功了!

AppStore-4

同時,也確認 Develop 分支下的包 ID:

App-環境管理-19

和 Master 分支下的包 ID:

App-環境管理-20

完成了!

哇,我們現在環境配置與建置已經非常完整了!

進階:Firebase 配置也可以分環境?

App 中常常會加入 Firebase 來使用,是很棒的工具庫,那我要如何將 Firebase 也換環境呢?

我們知道 firebase 都有一個設定檔案 GoogleService-Info.plist。如果我想依照環境設置不同的設定檔案,該如何做?

設置 Firebase

首先,讓我們建立專案:

Firebase-1

然後,加入 iOS App:

Firebase-2

讓我們輸入 Release 的基本資訊 :

Firebase-3

接著,安裝 Pod:

Firebase-4
Firebase-5

並初始化 SDK:

Firebase-6

然後,重複上面的步驟,也輸入 Debug 和 Staging 的包 ID,建立讓 Debug 和 Staging 用的 Firebase。

然後,將下載下來的檔案,分別命名成

  1. GoogleService-Info-Debug.plist
  2. GoogleService-Info-Staging.plist
  3. GoogleService-Info-Release.plist

最後來加一個腳本,內容如下:

Firebase-7

如此一來,App 就會在編譯期間抓取需要的設定檔案,實現分離環境讀取 firebase 設定!太棒了,連 firebase 都可以分環境了!

進階:Slack 通知

我們幾乎將所有實戰中遇到的問題都配置完成了!接下來,讓我們看如何更完整,把 Slack 通知也一併的配置進來。

我們的目標是讓 ChatOps 活起來,如此一來團隊中每個成員都可以很好的知道目前 App 的動向。

很簡單,我們只需要修改 Fastfile,加入 slack插件,將 slack url 替換成自己設置好的 webhook 就可以了!

最後再加入我們的 Deploy 中:

完成了!讓我們來看一下訊息:

slack-1

總結

大功告成!到目前為止,我們完成了真正一個產品開發的環境管理。因為有變數的關係,理論上是所有服務都可以分環境的,FB SDK、Line SDK 等等,授權與認證完全可以用變數的方式取代,CI/CD 也大大簡化了人工分環境的困擾與繁瑣的流程。同時,我們也成功地引入 DevOps、 Code as Infrastructure 的精神。

希望你喜歡本篇文章,如果你有不同的想法或問題,歡迎留言或電郵給我。感謝你的閱讀,祝你有個美好 Coding 夜晚,我們下次見。

別忘了,你可以在這裡下載原始碼作參考。


自認為終身學習者,對多領域都有濃厚興趣,喜歡探討各種事物。目前專職軟體開發,系統架構設計,企業解決方案。最喜歡 iOS with Swift。

blog comments powered by Disqus
Shares
Share This