Sparkle 自动更新部署应按完整发布链路实施:先配置更新源与更新包签名,再用真实旧版本验证检查、下载、安装和启动。适合站外分发 macOS App 的个人开发者与小团队;本周先选定分发路径,并准备一份仍在使用的旧版本做验收。
时间表|本周建议动作:先核对已发布客户端,再接入 Sparkle、生成首份 appcast,最后从旧版走完升级闭环。不要把“网页能下载新包”当作自动更新已经部署完成。
这篇适合首次为 macOS App 接入自动更新的开发者,也适合准备替换手动下载流程的维护者。没有本地 Mac、仍需负责构建与发布的小团队,也可以据此检查远程 macOS 环境能否承担这项工作。
先定分发边界:站外更新还是 Mac App Store
本文聚焦网站等站外渠道分发的应用。若应用通过 Mac App Store 分发,更新由商店渠道管理;Sparkle appcast 不应被当成同一套更新机制。Apple 将站外分发列为由开发者管理更新,并说明 Developer ID 与公证适用于站外分发的安全流程。可先核对 Apple 的 macOS 软件分发说明 与 Developer ID 签名指南。
部署前先盘点已发布版本,否则新配置即使对当前构建有效,也可能让旧客户端无法识别更新:
- 当前发行版内集成的 Sparkle 版本,以及用户实际使用的旧版本范围。
CFBundleVersion的现有格式与递增规则。Sparkle 用它比较应用版本,不要只改界面显示的版本号。- 当前用户下载的更新包格式,以及旧版客户端是否支持该格式。
- 站外分发的 Developer ID 签名、公证流程是否已经建立;这与 Sparkle 更新包签名不是一回事。
Apple 的公证是对 Developer ID 签名软件进行自动化检查,不等同于 App Review。站外发布时,按应用分发形式核对签名和公证要求;不要把“已生成 Sparkle 签名”误认为“已完成 Apple 代码签名或公证”。具体要求可查阅 Apple 公证 macOS 软件的官方说明。
第一步:让应用连到正确的更新源
Sparkle 的 SUFeedURL 指向 appcast,也就是客户端检查更新时读取的 feed;它不是应用下载页面,更不是更新归档的下载地址。更新归档地址会写在 appcast 对应版本条目中,三者不能互换。官方文档说明,appcast 是带有 Sparkle 更新信息的 RSS feed,并要求应用使用递增且格式正确的 CFBundleVersion。(Sparkle 官方文档)
在 Xcode 的目标配置或应用 Info.plist 中检查更新设置。下面只展示字段关系,示例值均为占位符:
<key>SUFeedURL</key>
<string>https://updates.example.invalid/appcast.xml</string>
<key>SUPublicEDKey</key>
<string>BASE64_PUBLIC_KEY_PLACEHOLDER</string>
SUFeedURL 决定客户端到哪里检查;SUPublicEDKey 提供验证更新归档签名所需的公钥。不要把私钥放进这个文件,也不要把下载页 URL 填成 feed 地址。
接入时还要确认构建版本会随发布递增。若应用显示版本已经更新,但 CFBundleVersion 没按既定规则改变,用户端就可能出现“新版本没有出现”的判断结果。不要在正式 feed 上直接试错:先用测试环境或受控发布目录核对 URL、XML 和版本比较。
第二步:建立 Sparkle 签名,不要混淆信任链
站外发布至少有几项容易被混为一谈的工作:
- Apple Developer ID 代码签名:让系统识别站外分发的应用开发者。
- Apple 公证:Apple 对符合流程的软件进行检查并生成公证票据。
- Sparkle 更新包签名:由 Sparkle 验证所下载的更新归档,防止归档内容被替换。
- appcast 文件签名:可选的 feed 与更新说明验证机制,不等于更新归档签名。
按 Sparkle 官方流程,generate_keys 生成 EdDSA 密钥,并输出要加入应用的公钥;签名私钥必须谨慎保管。之后,generate_appcast 可为更新归档生成签名。也可以通过 sign_update 手动签名,但无论采用哪种方式,都要在发布前确认签名与实际上传的归档对应。流程细节见 Sparkle 发布更新说明 和 Sparkle 的密钥与更新安全说明。
密钥管理不要靠提交仓库或复制进脚本来“方便自动化”。Sparkle 安全与可靠性文档指出,较新的工具已弃用把私钥直接作为命令行参数传入的做法;CI 环境应按工具支持的安全输入方式配置。若要在不同 Mac 间迁移密钥,先验证可恢复流程,再清理临时文件与访问权限。
第三步:生成 appcast,并把文件一起发布
普通应用归档可以先放入专用更新目录,再运行 Sparkle 随附的 generate_appcast。工具会生成 appcast,并可能按适用条件生成增量更新文件;随后要一并部署 appcast 与其引用的更新归档。Sparkle 也允许手工维护 feed,但官方推荐使用生成工具,能减少漏填签名和归档信息的机会。
发布前逐项检查:
- appcast 中的版本、更新说明与本次发布一致。
- feed 内归档 URL 指向最终发布位置,而非临时构建目录。
- 更新包已上传,且客户端访问时不需要开发者本机的登录态或文件权限。
- 重新下载发布文件后,签名验证对应的是这份归档,而不是本地另一个同名文件。
- 若开启签名 feed,修改 appcast 或更新说明后重新生成相应签名。
Sparkle 从 2.9 起支持签名 feed;启用 SURequireSignedFeed 时,还需要启用 SUVerifyUpdateBeforeExtraction。文档给出的 feed 签名失败过期时间默认值是 1,728,000 秒(20 天),但这不是建议直接照搬的密钥轮换策略;启用前要理解失败处理和回退行为。(Sparkle 自定义配置说明)
旧版升级验收:从用户手里的版本走完整条链
首发前要从仍在使用的旧版本开始测试,不要只在开发机安装新构建。把应用显示版本、CFBundleVersion、归档文件名和 appcast 条目记在同一份发布记录里,便于核对用户看到的版本是否对应实际安装包。
按以下顺序验收:
- 在测试环境安装仍受支持的旧版应用,确认它使用的 feed 地址和 Sparkle 能力。
- 让旧版请求 appcast,检查 feed 能访问、内容可解析,且返回了预期的新版本。
- 下载 appcast 引用的归档,确认文件可获取,再核对 Sparkle 签名验证结果。
- 执行更新安装,观察应用是否退出、替换并重新启动;不要只检查下载完成提示。
- 启动更新后的应用,核对应用显示版本与构建版本,并检查关键数据和启动行为。
如果失败,按症状分层定位:请求失败先看更新源与资源可达性;feed 可读但无更新,核对版本比较与旧版能力;下载成功但拒绝安装,检查签名和归档对应关系;安装后异常,则回到应用自身启动、数据迁移和日志检查。Sparkle 的旧版升级与 EdDSA 迁移指南提醒,历史客户端的签名能力及兼容路径可能不同;不要假设所有旧用户都支持同一套新配置。(Sparkle 升级说明)
什么时候选自动生成,什么时候保留手工维护
- 若发布的是常规应用归档、密钥可由发布环境安全访问,优先用
generate_appcast,再人工复核生成结果。 - 若有特殊安装流程或需要逐项控制 feed 内容,可评估手工维护;但必须自行持续核对版本、下载地址和签名字段。
- 若旧客户端仍使用不同签名机制或更新包格式,先用代表性旧版验证迁移路径;未验收前,不要移除仍被旧客户端依赖的兼容信息。
以下迁移细节尤其不能凭新版本测试结果推断:Sparkle 的 DSA 到 EdDSA 迁移指南给出了特定旧版、密钥和 Developer ID 条件下的处理路径。实际是否能简化迁移,取决于现存客户端与签名状态,应按 官方 EdDSA 迁移说明逐项核对。
常见问题:把接入、发布和环境边界拆开判断
macOS App 自动更新从哪一步开始?
先确定分发渠道和已发布客户端,再配置 Sparkle 的 feed、公钥与构建版本。先盘点旧版,比直接改当前工程更稳妥;否则新版本即使发布成功,老用户也可能无法理解新归档或签名。
更新归档与 appcast 的生成和签名要怎样安排?
常规归档可用 generate_appcast 自动生成 appcast 与归档签名,再将 feed 和引用文件一并部署。手工维护不是免验收方案,仍需检查每个版本条目的地址、版本字段和签名是否匹配。
发布后怎样验证旧版可以升级?
从仍在使用的旧版启动更新检查,依次验证 feed、版本判断、下载、签名、安装和新版本启动。把每一步结果分开记录,才能区分资源不可达、版本未识别、签名失败与应用升级后异常。
没有本地 Mac 能不能部署?
可以评估远程 Mac 作为 macOS 构建、代码签名和发布验证环境,但还要确认证书与密钥访问、构建自动化、文件上传以及旧版验收都能在目标环境完成。远程桌面可连接,只能证明可以登录,不能证明无人值守发布链已通过验收。
持续发布:把可回退记录和远程构建纳入流程
每次发布都保存同一组可追溯信息:构建版本、归档文件、appcast 变更、更新说明、签名验证结果和回退所需的旧文件。发现 feed 指向错误归档时,先恢复已知可用的 feed 与资源,再调查构建产物;不要覆盖唯一的旧发布记录。
签名密钥轮换前,先确认存量客户端如何信任新密钥、是否需要过渡发布,以及回退版本是否仍可验证。Sparkle 的升级说明和迁移指南提供了不同场景的兼容条件,不能把一条迁移路径套给全部历史版本。
按条件选择发布环境:
- 若发布频率低、现有 Mac 可稳定完成构建与验收,且磁盘和权限够用:继续本地发布,把签名材料与发布记录纳入维护。
- 若团队没有本地 Mac,但需要 macOS 构建、签名和旧版验收:评估远程 Mac,并先验证密钥访问、归档上传和完整升级链路。可先查看 MESHLAUNCH 的远程 Mac 方案,按实际发布流程判断是否匹配。
- 若流程要求长期无人值守、严格控制密钥访问或连接实体硬件:不要因为远程桌面能用就直接迁移;先完成权限审查与自动化验收,必要时保留自有 Mac 或现有构建环境。
手动发布往往需要逐次操作、容易漏掉 feed 与归档同步,也不容易复现旧版验收;本地专用 Mac 则要承担购置、维护与闲置时的成本。若当前缺少 macOS 环境、但需要阶段性完成构建与签名验证,可以比较远程 Mac 的使用与租赁选择。如果发布依赖实体接口,或需要长期稳定重负载,租赁未必合适;应先以一次真实发布验证环境、权限和回退流程,再决定是否把 Sparkle 自动更新部署迁入 MESHLAUNCH。