Highlight
Apple 在 Xcode 中提供专用于 Mac 应用公证的 notarytool,让 App Store 外分发的 Mac 软件可以用一条命令提交并等待公证结果,同时支持更快上传和 CI 回调。
核心内容
Mac 应用如果不通过 App Store 分发,发布前通常要走 Notarization(公证)流程。开发者把软件交给 Apple,Notary 服务检查恶意内容和代码签名问题。通过后,Apple 发布 ticket(票据),macOS 在用户启动应用时检查它。
过去用命令行做这件事,常见入口是 altool。它覆盖 App Store 和 Notary 多类任务。对只想给 Mac 应用做公证的开发者来说,流程太绕:先提交压缩包,再拿提交 ID,随后反复查询状态。CI 脚本还要解析命令输出,判断任务是否结束。
WWDC21 这场 session 给出的改变是 notarytool。它是新的 Notary 客户端,随 Xcode 分发,目标只放在公证流程上。submit 命令加上 --wait 后,客户端会上传、等待处理、返回结果。
这个变化解决的是发布链路里的等待问题。修完一个 Mac 应用 bug 后,开发者可以把归档、压缩、提交公证、等待结果放进同一条自动化流水线。Notary 服务还新增了专用 backend,并将多数开发者的上传速度提升到最高 4 倍。
从轮询脚本到单行命令
以前的脚本重点在“等”。提交完成后,CI 必须每隔一段时间查一次状态。状态仍是 in progress 时继续睡眠,结束后再进入下一步。
notarytool 把这个等待逻辑移进客户端。开发者写的是一次提交,工具处理的是上传和等待。脚本少了循环,也少了对文本输出的解析。
从本地等待到 CI 回调
CI 流水线不一定适合一直占着一个任务等待结果。Apple 在 session 中提到 webhook notifications(Webhook 通知)。提交时指定一个 URL,Notary 处理完成后会回调服务器。
这让公证结果可以反向触发后续步骤。收到通知后,CI 再拉取结果和 Notary log(公证日志),决定是否继续发布。
详细内容
Notary 服务检查什么
(01:23)Notarization 的流程很短:构建软件,提交到 Notary,等待自动分析,拿到结果,随后分发给用户。Notary 会扫描恶意内容,并检查代码签名问题。
Build Mac software
Submit to Notary service
Automated analysis scans for malicious content
Automated analysis checks code signing issues
Notary publishes a ticket when there are no issues
macOS checks the software before launch
关键点:
Build Mac software:开发者先完成构建和打包。Submit to Notary service:公证发生在分发前。Automated analysis scans for malicious content:Notary 会做恶意内容扫描。Automated analysis checks code signing issues:代码签名问题也会进入检查。Notary publishes a ticket when there are no issues:没有问题时,服务发布 ticket。macOS checks the software before launch:用户启动软件前,macOS 会检查该软件。
Apple 在演讲中给出处理时间目标:98% 的 Notary 提交会在 15 分钟内完成,大多数在 5 分钟内完成。这个数字适合放进发布流程的超时设置里。
altool 的轮询流程
(04:10)altool 的命令行流程分成两段。第一段提交应用,第二段循环查询提交状态。
# with altool
xcrun altool --notarize-app -f path/to/submission.zip \
--primary-bundle-id "$BUNDLE_ID" \
--apiKey "$KEY_ID" --apiIssuer "$ISSUER"
while true; do
INFO_OUT=$(2>&1 xcrun altool --notarization-info "$SUBMISSION_ID" -u "$USER" \
--apiKey "$KEY_ID" --apiIssuer "$ISSUER")
STATUS=$(echo "$INFO_OUT" | grep "Status:" | sed -Ee "s|.*: (.*)$|\1|" )
if [[ "$STATUS" != "in progress" ]]; then
break
fi
sleep 30
done
关键点:
xcrun altool --notarize-app:通过altool提交待公证的压缩包。-f path/to/submission.zip:指定提交文件。--primary-bundle-id "$BUNDLE_ID":传入主 bundle 标识符。--apiKey "$KEY_ID" --apiIssuer "$ISSUER":使用 App Store Connect API key 信息认证。while true; do:进入无限循环,直到公证状态变化。xcrun altool --notarization-info "$SUBMISSION_ID":查询某个提交 ID 的公证信息。INFO_OUT=$(2>&1 ...):把命令输出保存到变量,包含标准错误输出。grep "Status:" | sed -Ee ...:从文本输出中提取状态。if [[ "$STATUS" != "in progress" ]]; then break:状态不再是处理中时退出循环。sleep 30:每 30 秒查询一次。
这段脚本的脆弱点在状态解析。输出格式一变,grep 和 sed 就可能拿不到预期值。发布脚本也会被等待逻辑占满。
notarytool 的提交和等待
(04:19)notarytool 给出的新路径是一条命令。submit 负责提交,--wait 负责等待结果。
# with notarytool
notarytool submit path/to/submission.zip --wait \
--key "$KEY_PATH" --key-id "$KEY_ID" --issuer "$ISSUER"
关键点:
notarytool submit:使用新的 Notary 专用客户端提交软件。path/to/submission.zip:提交的 Mac 软件压缩包路径。--wait:提交后等待公证结果,完成后显示提交结果。--key "$KEY_PATH":指定 API key 文件路径。--key-id "$KEY_ID":传入 key ID。--issuer "$ISSUER":传入 issuer 信息。
这里的关键变化是 --wait。开发者不需要自己写轮询循环,也不需要自己解析 Status: 文本。任务完成时,工具会显示提交结果。
查看失败原因和 Notary log
(04:36)公证结果返回后,开发者只差一个命令就能查看 Notary log。演讲没有展示具体命令,但明确说明新客户端可以直接查看结果详情,包括应用没有被公证的原因。
notarytool
submit software
wait for result
view Notary log
inspect reasons when software is not notarized
关键点:
submit software:提交软件进入 Notary 服务。wait for result:等待任务处理完成。view Notary log:用新客户端查看公证日志。inspect reasons when software is not notarized:失败时查看原因,用于修复签名或内容问题。
这对发布排错很重要。以前失败信息散落在提交、查询、日志获取几个步骤里。现在同一个工具覆盖提交、等待和查看详情。
Webhook 通知接入 CI
(04:52)Webhook notifications 是这场 session 的另一个新能力。提交到 Notary 时,开发者可以指定一个服务器回调 URL。处理完成后,Notary 会通知这个 URL。
Submit to Notary with a webhook URL
Notary finishes processing the software
Notary sends a server callback
CI retrieves the result
CI retrieves the Notary log
CI continues or stops the release workflow
关键点:
Submit to Notary with a webhook URL:提交时带上回调地址。Notary finishes processing the software:Notary 完成自动分析。Notary sends a server callback:服务端收到处理完成通知。CI retrieves the result:CI 根据通知获取公证结果。CI retrieves the Notary log:CI 同步拉取公证日志。CI continues or stops the release workflow:流水线根据结果继续发布或中止。
这个能力适合长流水线。构建任务不必一直阻塞等待,可以把“公证完成”作为后续任务的触发点。
核心启发
-
做什么:给 Mac 应用做一个一键发布脚本。
- 为什么值得做:
notarytool submit --wait把提交和等待合并,发布脚本可以少写轮询逻辑。 - 怎么开始:在现有打包脚本后追加
notarytool submit path/to/submission.zip --wait --key "$KEY_PATH" --key-id "$KEY_ID" --issuer "$ISSUER",成功后再进入上传或分发步骤。
- 为什么值得做:
-
做什么:把 Notary 结果接入 CI 状态页。
- 为什么值得做:Webhook 通知让 Notary 完成事件可以被服务器接收,适合展示发布卡在哪一步。
- 怎么开始:为 CI 准备一个接收回调的 URL,提交公证时配置该 URL,回调后拉取结果和 Notary log。
-
做什么:为公证失败建立自动归档。
- 为什么值得做:
notarytool可以查看失败原因和 Notary log,失败信息适合沉淀到构建产物里。 - 怎么开始:CI 在公证失败时保存 Notary log,并把日志链接附加到构建报告或 pull request 评论中。
- 为什么值得做:
-
做什么:为外部分发的 Mac 应用设置发布时间预算。
- 为什么值得做:Apple 给出 98% 提交 15 分钟内完成、多数 5 分钟内完成的服务目标,可以据此设计流水线超时。
- 怎么开始:把公证步骤的 CI 超时设为大于 15 分钟,记录每次提交耗时,发现异常时告警。
-
做什么:迁移旧的
altool公证脚本。- 为什么值得做:Apple 已将
altool用于 Notary 的路径标记为 deprecated,新的性能和可靠性改进需要切换到notarytool。 - 怎么开始:搜索仓库里的
--notarize-app和--notarization-info,将提交和轮询逻辑替换为notarytool submit --wait。
- 为什么值得做:Apple 已将
关联 Session
- Distribute apps in Xcode with cloud signing — 讲 Xcode 13 如何用 Cloud Signing 简化签名、归档和分发。
- Meet TestFlight on Mac — 讲 macOS 应用如何通过 TestFlight 进行测试分发,并连接 Xcode Cloud。
- Triage TestFlight crashes in Xcode Organizer — 讲发布前测试阶段如何在 Xcode Organizer 中处理崩溃和反馈。
- Review code and collaborate in Xcode — 讲 Xcode 中的代码审查和协作流程,适合放在发布流水线前段。
评论
GitHub Issues · utterances