一条空的更新源,怎么把老装机甩在了后面

一个更新按钮不等于一套更新系统。如果发现路径永远返回不了版本,那么提示、稍后提醒规则和安装器可以全部工作正常,而用户仍然被困在原地

Agent Island 的 macOS App 里本来就有更新框架,但它的源地址是空的。检查跑了,什么都没找到,然后安静地失败。老装机在 App 内没有任何路径可以得知 GitHub 上已经有了更新版本

这是一种危险的失败模式,因为它看起来很平静。没有崩溃,没有坏掉的按钮,也没有可见的错误。而受影响最深的那批人,恰恰用着那个收不到未来修复的版本

把版本发现和安装分开

Agent Island 1.7.1 里的修复,把「发现」当成一个独立的小系统来做

启动时,App 会等 20 秒再检查。这段延迟让会话发现和周报时刻先完成。之后一个重复定时器每六小时检查一次,带十分钟的容差,好让操作系统有空间去合并唤醒

查询调用仓库的 latest-release 接口,超时 15 秒。一个成功的响应需要 HTTP 200 和一个 tag_name。做点分十进制比较之前会先去掉前导的 v,所以 1.10.0 正确地排在 1.9.9 之后,段数不等的用零补齐

接口同时返回发布页地址。macOS 的更新按钮打开那个页面,而不是假装 App 有一条已验证的静默安装路径。Windows 保留它已有的 App 内下载与重启流程,但用的是同一套发布节奏和稍后提醒策略

发现和安装是两种不同的能力。共用一条发现规则,并不要求你去声称两个平台安装更新的方式也一样

后台检查要安静,手动检查要给答案

自动路径有三个提前退出:

  1. 自动检查被关掉了
  2. 拉不到最新版本
  3. 该版本不比当前新,或者这个版本被设置了稍后提醒

三种都不产生提醒。一次后台检查里的网络失败,不该每六小时就打断用户一次

设置里的操作遵循另一份合同。点了「立即检查」的人应该拿到一个答案:一个新版本提示、一句已是最新,或者一条清楚的失败信息。因此同一个网络结果,在后台可以是静默的,在用户主动请求之后必须是明确的

这个差别在代码里很小,在使用中很重要。后台静默失败保护注意力,手动静默失败会让这个控件显得是坏的

稍后提醒针对的是版本,不是更新器

macOS 上的提醒给出两个操作:「更新」和「知道了」。选后者会同时存下这个发布版本号和一个七天之后的日期

版本这个键很要紧。一个对 1.7.1 点了稍后的用户,不该因此把这一周里新发布的 1.7.2 也压掉。只按日期做稍后提醒,就会正好造成这个后果

它也避开了第二种失败模式:每隔六小时就为同一个发布提示一次。App 可以坚持,但不必变吵

旧版边界打补丁是打不掉的

新的检查器随 1.7.1 一起发布。1.6.1 及更早的版本里没有它,它们那条旧的源仍然是空的。这些装机没法通过一个只有 1.7.1 才引入的机制,得知 1.7.1 的存在

对这些用户,诚实的迁移指引是手动下载或者 brew upgrade。装上 1.7.1 之后,之后的版本就能在启动时和六小时节奏里被发现

发布说明常常写一句「新增更新检查」,却不点明这个自举边界。这个省略会造成一种印象:这个功能能覆盖每一台现有装机。它不能

该测什么

发布轮询需要的不只是一个顺利路径的接口桩

版本比较应该覆盖段数不等和两位数的分量。检查器应该忽略当前已装版本、更旧的发布、畸形的 JSON、非 200 响应和超时。稍后提醒应该只挡住存下来的那个版本,并在期限之后失效。自动设置必须只管住后台检查,而不能把用户的手动命令一起禁掉

呈现层还需要一道单提醒守卫。两次同时完成的检查,不该把模态提示叠起来

最后,测你对每个平台做出的那个声称。共用一次接口查询,证明不了共用一个安装器、签名路径或重启行为

一套投递系统要把被困住的那个版本也算进去

这里的技术工作量不大:一次接口请求、一个定时器、一次版本比较,加两个用户偏好键。运维上的教训要大得多

更新系统有一个自举问题:那个修好了发现路径的版本,没法用这条修好的路径去触达没有它的用户。产品文案、支持指引和渠道更新必须把这个缺口扛住,直到老用户群往前挪完

Agent Island 1.7.1 提供 macOS DMG 与 Windows x64 ZIP,免费且采用 MIT 许可。用着更老 macOS 版本的用户,需要手动更新一次,App 内的版本发现才开始工作