作者团队插件发布Job三周内持续显示成功,但Marketplace实际未上架。根因是发布脚本将「待审核状态」误判为无害错误并返回0,导致CI误报成功。
三周绿灯,无一安装
这件事就发生在我们身上。我们 JetBrains 插件的发布任务自七月中旬以来每次运行都报告成功。但插件压根就不在市场上。
注册表 API 返回了 404。按产品名搜索什么都找不到。与此同时构建是绿的、发布说明写好了、变更日志也更新了。
没有人注意到。管道没注意到,仪表盘没注意到,我们也没注意到。从上一次正常发布到发现这个问题,中间隔了三周。
你的管道没有骗你
这部分值得理解,因为同样的问题很可能正潜伏在你的代码库里。
发布管道只有一项工作:把产物放到陌生人能安装的地方。几乎每个管道检查的都是别的东西——它检查上传命令是否以零退出。
这两个问题绝大多数时候结论一致。我们的发布步骤更进一步,做了合理的事:捕获失败、将错误文本与已知无害的情况列表对比,对这些情况返回零退出。
其中一种情况是"待审核"。新版本在可见之前会处于审核状态。为此让构建失败就是噪音,所以被放行了。
这就是陷阱。无害的瞬时状态和永久阻塞产生相同的消息。一旦插件卡住,后续每次运行都匹配同一个友好的模式并报告成功。管道正确地回答了它的问题。只是这个问题本身是错的。
两分钟就能补上的检查
问商店,而不是问管道。这就是全部思路,今天就能加上去,不需要改别的东西。
第一:发布后,用陌生人的方式获取公开列表。不带凭证、不用内部 API、不使用认证客户端。看到外部人员看到的东西才是关键。
第二:从响应中读取版本号,与清单文件中的版本比较。不是与你刚构建的版本比,也不是与任务中的变量比。而是与提交入库的文件比。
第三:每个发布渠道打印一行,说明哪个无法访问。已访问、无法访问、或过时。绝不输出裸零。
最后这点比看起来重要。一个错误退出的数据源被计为零,看起来和安静的一天完全一样。
在信任它之前,先让它故意失败
一个从没亮过红灯的监控只是个希望,配了一个日志文件。
给它一个清单过时的 fixture,断言它非零退出。运行一次,看看红色长什么样。只需几分钟,而这是区分真实检查和自我安慰的唯一方式。
我们在另一个监控上跳过这一步。它在那里坐了好几周,什么都不报告,而什么都不报告和一切正常之间无法区分。
一旦你见过这种形态,你会发现它无处不在
写入工作区的缓存文件会在下一次运行时被清除。日报的增量是基于一个种子示例行计算的。返回一个 HTTP 错误的数据源被计为零。
每一个都是绿的。每一个都没有产出。
缺失的成分总是一样的:第三种状态。系统对成功和失败建模,却忘了"未测量"。没有它,停机与安静的一天无法区分,而人们还是会依据那个数字行事。
两分钟换来的收获
三周的停机变成第二天早晨的一条消息。这就是全部的交换。
它还能捕获退出码无法触及的情况:上传确实成功了但清单仍未更新。从外部看这两种情况完全一样,而你的用户是在外部。
我们的版本读取三个公开端点,将它们与代码库中的清单对比,然后每个打印一行。它不带凭证。每天运行一次,无论我们当天是否发布了任何东西。
我们打开它的那天,它是红的。