WWDC Quick Look 💓 By SwiftGGTeam
Faster and simpler notarization for Mac apps

Faster and simpler notarization for Mac apps

观看原视频

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:10altool 的命令行流程分成两段。第一段提交应用,第二段循环查询提交状态。

# 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 秒查询一次。

这段脚本的脆弱点在状态解析。输出格式一变,grepsed 就可能拿不到预期值。发布脚本也会被等待逻辑占满。

notarytool 的提交和等待

04:19notarytool 给出的新路径是一条命令。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:流水线根据结果继续发布或中止。

这个能力适合长流水线。构建任务不必一直阻塞等待,可以把“公证完成”作为后续任务的触发点。

核心启发

  1. 做什么:给 Mac 应用做一个一键发布脚本。

    • 为什么值得做notarytool submit --wait 把提交和等待合并,发布脚本可以少写轮询逻辑。
    • 怎么开始:在现有打包脚本后追加 notarytool submit path/to/submission.zip --wait --key "$KEY_PATH" --key-id "$KEY_ID" --issuer "$ISSUER",成功后再进入上传或分发步骤。
  2. 做什么:把 Notary 结果接入 CI 状态页。

    • 为什么值得做:Webhook 通知让 Notary 完成事件可以被服务器接收,适合展示发布卡在哪一步。
    • 怎么开始:为 CI 准备一个接收回调的 URL,提交公证时配置该 URL,回调后拉取结果和 Notary log。
  3. 做什么:为公证失败建立自动归档。

    • 为什么值得做notarytool 可以查看失败原因和 Notary log,失败信息适合沉淀到构建产物里。
    • 怎么开始:CI 在公证失败时保存 Notary log,并把日志链接附加到构建报告或 pull request 评论中。
  4. 做什么:为外部分发的 Mac 应用设置发布时间预算。

    • 为什么值得做:Apple 给出 98% 提交 15 分钟内完成、多数 5 分钟内完成的服务目标,可以据此设计流水线超时。
    • 怎么开始:把公证步骤的 CI 超时设为大于 15 分钟,记录每次提交耗时,发现异常时告警。
  5. 做什么:迁移旧的 altool 公证脚本。

    • 为什么值得做:Apple 已将 altool 用于 Notary 的路径标记为 deprecated,新的性能和可靠性改进需要切换到 notarytool
    • 怎么开始:搜索仓库里的 --notarize-app--notarization-info,将提交和轮询逻辑替换为 notarytool submit --wait

关联 Session

评论

GitHub Issues · utterances