iOS自动化打包之重签名导出不同证书ipa探索

在完成基础的自动包打包流程过后,随即也出现了日常中常见的问题,比如我们每次需要打出不同网络环境和不同证书的ipa,由于开发者可以添加的设备只有100个,而公司的几个项目都是用的一个账号,各项目组都是独立的,再加上期间加入设备的员工的离职,真正能参与测试的设备寥寥无几。

所以我司一般测试都是使用企业证书,这样不同的项目都可以公用同一个证书,不仅管理起来方面,而且还摆脱了设备数量限制的烦恼,但另一方面,对于需要测试内购等功能的时候,仍然需要使用adhoc证书的包来进行测试。

我们原先的打包策略是通过执行脚本时输入的参数来打对应的包,这样对于不同测试并行测试,一次就要打出好几个,以我司作为打包服务器 Mac Mini 来说,archive + export 一个包的时间约为20min,对于不同证书不同环境的包随机组合,一次打出4个不同的包的时间就要花费约1h20min,而且在打包的时候,如果其他同事修改了新的bug,也无法打包。

因此,我们寻思能不能通过重签名的方式,只编译一次,对其重签名,打出不同的包。

本文主要介绍我在此过程中的一些探索,旨在提高不同证书不同环境的打包效率。

对ipa进行重签名

起初,我在网上查阅了相关资料,按照相关教程,却最终以失败告终。 如果有同学直接对ipa进行重签名成功的,希望不吝赐教。

我估摸着是不是内部做了什么验证,导致对ipa重签名无法成功。所以,我想可不可以不到ipa这步,更早地对其进行信息的修改以及重签名,权当一次尝试,即使失败也能在探索中学到新知识。最终,成功将原来打4个包需要1h20min的时间压缩到30min不到。

不等导出ipa,修改.xcarchive文件

.xcarchive文件是对项目进行手动archive,或执行以下脚本:

1
xcodebuild archive -workspace ${work_space} -scheme ${scheme} -configuration ${configurationDistribution} -archivePath ${archivePath}

如果对打包命令不是很了解的,可以查看我的上一篇文章文章:关于iOS自动化打包的一些分享

首先,我们进入到 .xcarchive 文件目录,发现里面一个 Info.plist 文件,打开如下显示:
xcarchive_infoplist.png

我们可以看到里面有一些App必需的属性。

1. 修改 .xcarchive 的 Info.plist

此处,如果项目 Bundle Identifier 需要发生改变,则修改 CFBundleIdentifier 对应的值,并将 SigningIdentity 改成 Bundle Identifier 对应的证书,关于此处SigningIdentity的值,可在钥匙串中找到对应的证书,查看其信息,即为下图中(英文系统)的 Common Name 。

certificate_info.png

2. 修改 App Extension 相关信息

此步是对于项目 target 中如 notification extension 等从属 target,如果没有 App Extension ,直接可以跳过此步,查看下一步 修改主target相关信息

通过文件夹打开 YourAppName.xcarchive/Products/Applications/YourAppName.app/PlugIns/YourAppNameNotificationServiceExtension.appex ,这里不是标准文件夹,open 命令似乎不起作用,观察其目录结构:

extension_floder.png

2.1 修改 Info.plist 相关信息

App Extension 的 Bundle Identifier 是 App 的 Bundle Identifier 加上其对应后缀,如 notificationserviceextension 。

修改 Bundle Identifier 为对应的值,这里对应的值是指之前修改 .xcarchive 目录中 Info.plist 的 Bundle Identifier 对应,如 com.test.www ,这里便是 com.test.www.notificationserviceextension

extension_infoplist.png

2.2 替换 Provisioning Profile

将对应的 Provisioning Profile 拷贝到该目录下替换原来的 Provisioning Profile ,改成相同的文件名 embedded.mobileprovision

2.3 修改 archived-expanded-entitlements.xcent

我们通过xcode打开archived-expanded-entitlements.xcent,其本质就是plist文件,
格式是 teamId.bundle identifier

extension_archived-expanded-entitlements.png

修改图中遮盖的两项值,依旧是要和.xcarchive的Info.plist值对应。

2.4 重签名

用对应的证书对 App Extension 重新签名,这里的 YourCetificateName 依旧是修改 .xcarchive的Info.plist 里的证书名。

1
codesign -f -s "YourCetificateName" YourAppNameNotificationServiceExtension.appex

3. 修改主target相关信息

与上一步修改 App Extension 步骤基本相同,只是少一步,不用修改 archived-expanded-entitlements.xcent 。

3.1 修改Info.plist的相关信息

进入.app目录,修改Info.plist的Bundle Identifier,使其与.xcarchive文件对应。

你也可以修改其他一些值,如网络环境,是测试环境,还是生产环境,这里只是抛砖引玉。事实上,修改网络环境有方便的方法,如通过读取粘贴板的文本来切换,或者写一个辅助程序来打开我们的App,从而通知切换环境。

3.2 替换Provisioning Profile

将对应的 Provisioning Profile 拷贝到该目录下替换原来的 Provisioning Profile ,改成相同的文件名 embedded.mobileprovision

3.3 重签名

用对应的证书对 .app文件 重新签名,这里的 YourCetificateName 依旧是修改 .xcarchive的Info.plist 里的证书名。

1
codesign -f -s "YourCetificateName" YourAppName.app

4. 导出包

1
xcodebuild -exportArchive -archivePath YourAppName.xcarchive -exportPath $(pwd) -exportOptionsPlist YourExportOptionsPlistPath

成功后,命令台输出:

export_succeed.png

如果对于 exportOptionsPlist 不了解的,也可以看我的上篇文章:关于iOS自动化打包的一些分享

注意点

上述修改的每一步,无论是Bundler Identifer,还是Provisioning Profile,还是重签名用的证书,都是需要相对应的,如果有一步错了,ipa包是导不出来的。

我的表述可能不是那么清楚,相信大家操作一次,一步一步来,修改需要修改的值,其实基本是一目了然的。
大家如果有类似需求,建议先操作一次,成功后再写脚本实现自动化。

总结

经过上述操作,实质上只进行了一次编译,然后修改相关信息,导出对应不同的证书的包,只是多做了几次导出操作,大大地节省了打包时间。大家如果有什么想法或更好的办法,欢迎一起讨论讨论。