1. 前言
match
這個Tool的作用可以分為兩步
- 獲取合適的cert和profile
- 將獲取的cert和profile安裝到本機
其簡單流程如下圖所示
- 首先,從
:git_url
指定的git倉庫中獲取cert和profile,如果沒有,則從AppleID賬號中獲取。 當從AppleID賬號中獲取cert時,即使你的AppleID賬號中有建立好的簽名證書,match
也只會嘗試去建立一個新的的簽名證書,如果你的AppleID賬號中籤名證書的數目已達到了2個,則會建立失敗,然後match
異常退出; 當從AppleID賬號中獲取profile時,會強制建立一個新的來使用。具體過程可檢視上一節cert和sigh。 match
的最終目的就是把cert和profile安裝到本機 cert被匯入到鑰匙鏈中 profile被安裝到xcode中
2. 內部流程
macth
特別適合在一個團隊裡面使用,在使用match
時,一般會先使用match
建立一套可使用的cert和profile上傳到git倉庫中,然後共享這個git倉庫給團隊的其他成員,這樣就可以一次建立,多次使用了。另外,macth
提供了一個只讀模式,可以防止你修改AppleID賬號中或git倉庫中的cert和profile。
2.1. 只讀模式
當:readonly
的值是true時,match不會訪問AppleID賬號,只會從git倉庫獲取cert和profile,並且不會修改git倉庫。在只讀模式中,:force
必須是false,否則,程式異常退出。在只讀模式中,:force_for_new_devices
不會生效。
- 從倉庫克隆cert和profile
通過
:git_url
指定git倉庫的地址,預設情況是克隆master分支,可通過:git_branch
指定分支。如果在同一個倉庫中管理多個team,可使用不同的分支來儲存不同的team。 克隆完畢之後,整個庫會被儲存在一個臨時地址中,庫的檔案結構如下圖所示
-certs
-enterprise
-#{cert_id}.cer
-#{cert_id}.p12
-development
-#{cert_id}.cer
-#{cert_id}.p12
-distribution
-#{cert_id}.cer
-#{cert_id}.p12
-profiles
-enterprise
-InHouse_#{bundleID}.mobileprovision
-appstore
-AppStore_#{bundleID}.mobileprovision
-adhoc
-AdHoc_#{bundleID}.mobileprovision
-development
-Development_#{bundleID}.mobileprovision
複製程式碼
上述檔案結構列出了certs/
和profiles/
目錄中所有可能的子目錄,具體使用哪個子目錄,則是由:type
指定,比如在使用企業賬號時,且:type
等於enterprise
,則certs目錄下會有一個enterprise子資料夾。
cert和profile檔案的命名必須按照上述格式,否則match會識別不出來。
:type
與子目錄名對照表
type | certs/下子目錄名 | profiles/下子目錄名 |
---|---|---|
enterprise | enterprise | enterprise |
appstore | distribution | appstore |
adhoc | distribution | adhoc |
development | development | development |
倉庫中儲存的cert和profile檔案都被OpenSSL加密過,所以克隆下來之後的第一件事就是解密,這時match需要一個密碼用來解密,可以通過環境變數MATCH_PASSWORD
來指定,如果沒有指定,則match會嘗試去鑰匙鏈的密碼列表中尋找名稱為match_#{:git_url}
的鑰匙串項,如果仍然沒有,則需要使用者手動輸入。在CI環境中,最好事先使用環境變數MATCH_PASSWORD
設定好。
match
使用類似下列終端命令的程式碼來加解密
#加密
openssl aes-256-cbc -k "<password>" -in "<fileYouWantToEncryptPath>" -out "<encryptedFilePath>" -a -e
#解密
openssl aes-256-cbc -k "<password>" -in "<fileYouWantToDecryptPath>" -out "<decryptedFilePath>" -a -d
複製程式碼
如果cert和profile已建立好,可以使用上述命令加密下載的cert和profile,然後上傳到git倉庫。
-
獲取bundleIDs 通過
:app_identifier
來指定bundleID,如果有多個bundleID,可以通過逗號分隔。 git倉庫的同一個分支中,可以存放多個app的profile,因為profile檔名中帶有bundleID,所以可以通過檔名來區分不同的app的profile。 -
從倉庫獲取cert 首先,根據
:type
指定的型別,假設其值為enterprise
,則match
遍歷倉庫的/certs/enterprise/
目錄下的所有檔案,將檔名符合*.cer
格式的最後一個當做簽名證書,將檔名符合*.p12
格式的最後一個當做其對應私鑰。 3.1 如果簽名證書和其私鑰都存在,則將簽名證書的檔名去掉副檔名,剩餘部分作為此證書的id。 3.2 如果簽名證書或其私鑰不存在,則異常退出。 (其詳細流程可檢視本文的第3小節) -
安裝證書到鑰匙鏈 match使用如下命令將[步驟3]中獲取的證書和其私鑰分別安裝到鑰匙鏈中
# certificate_path 表示要匯入證書的路徑
# keychain_path 表示鑰匙鏈的路徑,一般是`~/Library/Keychains/login.keychain-db`
# certificate_password 表示證書的密碼,預設是空字串,通過`cert`建立的證書的密碼為空
# -T usr/bin/codesign 表示使用`usr/bin/codesign`訪問這個證書的時候不需要授權,也就是不需要輸入鑰匙鏈的密碼,使用xcodebuild打包app的使用會使用這個命令
security import certificate_path -k keychain_path -P certificate_password -T /usr/bin/codesign -T /usr/bin/security
複製程式碼
-
從倉庫獲取profile 和[步驟3]類似,首先,根據
:type
指定的型別,假設其值為enterprise
,則match
遍歷倉庫的/profiles/enterprise/
目錄下的所有檔案,將檔名符合InHouse_#{bundleID}.mobileprovision
格式的最後一個作為要使用的profile。 5.1 profile存在,則執行[步驟6] 5.2 profile不存在,則異常退出。 (其詳細流程可檢視本文的第4小節) -
安裝profile到xcode 將[步驟5]中獲取的profile檔案複製到
~/Library/MobileDevice/Provisioning Profiles/
目錄下,檔名為#{uuid}.mobileprovision
,其中uuid
是profile的uuid -
然後正常退出
注意,在獲取cert和其私鑰時,match
只是粗略的通過副檔名來做篩選,並沒有驗證證書和其私鑰是否是一一對應的,所以不要把兩套cert放在同一個子目錄下。同理,在獲取profile時,也沒有驗證cert和profile中關聯的cert是否是同一個簽名證書。所以可能出現一種情況,macth
執行成功,但是app打包不成功。當然,如果你沒有手動修改git倉庫,只通過match
來建立和更新,則不會出現這種情況。
2.2 非只讀模式
當:readonly
的值是false時,如果git倉庫中沒有找到可用的cert和profile,則match
會從AppleID賬號中建立新的。
-
從倉庫克隆cert和profile
-
登入AppleID和選擇teamID
-
檢測type 當
:type
的值是enterprise,但你使用的AppleID賬號不是一個企業賬號時,異常退出。 -
獲取bundleIDs
-
檢測bundleIDs的可用性 遍歷bundleIDs,如果在AppleID賬號中不存在對應App ID,則異常退出,只要有一個不存在就會異常退出。
-
獲取cert 首先嚐試從git倉庫獲取cert,其具體流程和[2.1節的步驟3]完全一樣,如果git倉庫中沒有,則嘗試從AppleID賬號中建立一個新的簽名證書。 為了實現建立新的證書這一功能,
match
呼叫了cert
這個Tool,並設定cert
的:force
引數的值為true來強制建立,而不管本地鑰匙鏈中是否存在cert。如果建立成功,則下載建立的cert和其對應私鑰到git倉庫的子目錄certs/cert_type
中。 (呼叫cert
的詳細流程可檢視cert和sigh,本步驟的詳細流程可檢視本文的第3小節) -
安裝cert到鑰匙鏈
-
檢測cert可用性 檢測在[步驟6]中獲取的cert是否存在於AppleID賬號中,具體而言就是比較cert和AppleID賬號中獲取的cert的唯一識別符號是否一致。 從步驟6可知,有兩個途徑獲取cert,git倉庫和AppleID賬號。從AppID賬號中下載的cert肯定是沒問題的,這一步主要是驗證從git倉庫中得到的cert的唯一識別符號的可用性。上文中有提到,在git倉庫中獲取的cert的唯一識別符號就是這個cert去掉了副檔名之後的檔名。
-
獲取profile 和[步驟6]類似,首先嚐試從git倉庫獲取profile,如果git倉庫中沒有,則嘗試從AppleID賬號中建立一個新的profile。 假設
:type
的值為enterprise
,從git倉庫中獲取profile的具體流程是,遍歷倉庫中/profiles/enterprise/
目錄下的所有檔名符合InHouse_#{bundleID}.mobileprovision
格式的profile檔案,如果這個profile存在於AppleID賬號中,則返回這個profile。 為了實現建立新的profile這一功能,match
呼叫了sigh
這個Tool,並設定sigh
的:force
引數的值為true來強制建立,而不管AppleID賬號中是否已存在profile。同時,也指定了sigh
的:cert_id
引數的值為[步驟6]中獲取的cert的唯一識別符號。 (呼叫sigh
的詳細流程可檢視cert和sigh,本步驟的詳細流程可檢視本文的第4小節) -
安裝profile到xcode
-
提交cert和profile到倉庫 如果在[步驟6]建立了新的cert或在[步驟9]中建立新的profile,則需要將這些新建立的檔案新增到倉庫,並推送的遠端倉庫中。
3. 獲取cert
下圖是獲取cert的詳細執行流程
4. 獲取profile
下圖是獲取profile的詳細執行流程