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的详细执行流程
3. 获取profile
下图是获取profile的详细执行流程