Total Pageviews

Tuesday, 1 March 2022

macOS上的app实现自动化 notarize的脚本

根据苹果官方的说明,自 macOS 10.15 起,所有从互联网下载的未进行 notarize 的 app,默认将无法被打开,所以在 App Store 外分发的 app,也必须在发布前将 app 上传到苹果的服务器进行处理。

使用 Xcode 自带 archive 工具可以很方便地进行 notarize,但这个操作无法实现自动化处理,为了方便分发,我将 落格输入法 macOS 2 的分发流程都做成了自动化脚本,现在,只好给脚本添加自动化提交功能了。

命令工具

苹果官方实际上有提供cli 命令,首先你需要运行 xcode-select --install 来安装支持,然后我们使用 $ xcrun altool --notarize-app --primary-bundle-id "" --username "" --password "" --file "" 来上传app给苹果服务器;使用 $ xcrun altool --notarization-info -u "" 来轮询检查处理结果(尽管官方说在一小时内,但一般很快,几分钟就搞定);最后使用 $ xcrun stapler staple "" 来给文件盖章。

我应该提交哪些文件?

首先,我们要搞明白应该提交哪些(个)文件到服务器,比如,你有个 Great.app 这个编译结果,然后你可能还有一个 Great.pkg,用来给用户安装 Great.app,最后,为了分发方便,你可能还会把这个 pkg 文件放入 Great.dmg 中,这样,我们就有了三个文件:Great.app,Great.pkg,Great.dmg 。

实际上,Great.app 就是个目录,所以,如果你仅仅分发 app,那么你需要将 Great.app 打包成 Great.app.zip,然后再上传到苹果的服务器进行 notarize。

总之,如果你和我一样,一次有这么三个互相包含的文件,那么你【只需要】上传嵌套最多的 Great.dmg 即可,苹果的服务器会自动将你的 dmg 文件打开,取出 pkg,然后取出 app,并为【三者】完成 notarize。

这样,当 notarize 完成,我们虽然没有上传 app 和 pkg,但依旧可以为这两个文件单独完成 staple。

项目设定

实际上,当你在使用 Xcode 自带 archive 进行 notarize 时,它为你完成了很多工作,如果我们自己使用命令,则需要进行额外的配置,打开你的 Xcode 项目,project 的 Build Settings 中,设置代码签名包含时间戳,这是 notarize 必须的操作:

为所有项目的签名,增加时间戳

另外还有:
去掉debug文件,注意debug模式下,不要去掉,不然你就不能debug了。

上传

这里有几点要注意,首先上传结果输出到 tmp 文件供稍后获取查询id,注意使用 &> 而不是 > ,后者无法把输出的内容放入 tmp ;

对于 -itc_provider "your team id" 这个参数,如果你的 Apple ID 下只有一个开发者账号,那就不需要这个参数了,如果你和我一样,Apple ID除了自己的开发者账号,还加入了别人的组,那你就有了多个“ provider”需要手动指明是上传到哪个,要查看你的 provider ,到 App Store Connect,登录后在右上角点击菜单,选择编辑账号信息,你能找到一个叫做“Team ID”的字段,里边的内容就是;

对于 --primary-bundle-id "app bundle id" ,就是你app的 bundle id,如果你上传的是 Great.app.zip,那么这个参数不是必须的;

还有就是注意 --password "one-time-password"  这个参数,要生成一次性密码。


等待并完成

总之,上传成功之后,我们会得到 tmp 文件最后一行:

依靠这个 UUID,我们可以使用命令来检查 notarize 的状态实现等待,一旦成功,就可以 staple 了。

实际上返回的内容是这样的:

但我们只检测文中是否包含 success 即可,一旦包含,就使用 xcrun stapler staple "Great.app" 来完成 notarize。

接下来,就是原本的操作了,生成 sparkle 更新包,上传分发。

 

参考文献

----------------------

使用 xcodebuild 来 archive 并导出 app


上面的文章并没有提到使用代码自动编译并生成 App 的脚本,毕竟这一步有好多工具可以完成,比如说 fastlane。

我由于在 notarize 之前也没想过做自动化,而在写那篇文章的时候 fastlane 还没有支持 notarized 上传,于是我就自己写了,具体的编译命令是这样的:

这样就可以直接把 dsym 和 app 文件生成出来了,方便的很。

……可是好景不长,最近苹果似乎改动了 notarized 服务器行为,之前就一直让人头疼的 sparkle 集成签名问题再度出现,简而言之就是每次使用脚本生成的 app,对 sparkle 的签名总是出现各种问题,而本地检测又是正常的。

作为对比,使用 Xcode 自己的 archive 生成并上传,是一切正常的(我单独给 Sparkle 做了额外的签名代码,是可行的,但用命令编译就不行)。

我猜测可能是直接生成 App 丢失了什么缓存,经过查询,现在分为两步走,先生成正常的 archive ,然后再从 archive 中导出 app。

生成 xcarchive ,这一步没什么好说的,直接就能成功了,接下来的步骤则有点复杂:

选择你刚刚生成的 xcarchive,然后从里边导出 app(并签名),这一步要求了一个奇怪的 -exportOptionsPlist ,且目前在网上也找不到什么完整的模板,总的来说这个配置文件是不用写满全部参数的,把主要参数写了就行,其他参数按默认即可,以前的 Xcode 版本还可以从 archive 功能里导出一份配置文件(这个文件在导出时也存在一份拷贝),现在似乎不能了,总之,我给出一个模板,你可以参考来写,反正如果写错了,它会报错,然后告诉你缺少什么参数,又或者哪个写错了,应该是哪些之一,很好排错:

比如上文中 teamID 和 signingStyle 字段,其实都可以省略,因为 xcodebuild 会自动从你的项目配置中读取。


这下导出的 app 就可以正常 notarized 了。

No comments:

Post a Comment