LGTM != Production Ready:为什么你的 CI 流水线缺少最重要的一步
Source: Dev.to

Overview
我们有用于语法检查的 linter 和用于安全检测的 scanner。现在是时候开始 lint “这会在凌晨 3 点把我叫醒吗?”了。
你提交了一个 Pull Request。CI 通过,显示绿色。你的同事审查后评论 “LGTM!” 代码被合并并部署。
三天后,凌晨 3:17,PagerDuty 触发警报。
根本原因并不是语法错误,也不是单元测试能捕获的逻辑 bug,而是一些微妙的问题:一个 HTTP 客户端缺少超时设置,导致在下游服务出现小故障时出现连锁失败。
“高级直觉”差距
为什么 PR 审查会遗漏那个缺失的超时?
- 标准的代码审查通常关注代码风格、逻辑正确性和可维护性。
- 标准的静态分析工具会捕获语法错误或明显的安全缺陷。
没有人在主动搜索运营成熟度。通常,捕获这些潜在的故障模式依赖于“资深工程师直觉”——即经过多年值班被叫醒的老练 SRE 所培养的蜘蛛感应。他们扫一眼代码就立刻想到:“退避重试逻辑在哪里?”或“这个未检查的环境变量迟早会导致启动失败。”
问题在于资深直觉无法扩展。你不能克隆出最优秀的 SRE 来审查每一个 PR。
检查清单的失败
许多组织尝试通过“Production Readiness Checklist”来解决这个问题——这是一页尘封的 Confluence 页面,上面有数十个问题,例如“你是否考虑过 failure domains?”
老实说,没人会使用这些。它们是手动的、繁琐的,在开发生命周期的最后阶段才完成(已经太晚无法更改架构),通常只是一场“checkbox theatre”,用来安抚管理层。
如果不是自动化的,它就不存在。
将“可操作性”前移
我们需要像对待代码风格一样对待运维需求。如果 gofmt 失败,就不能合并。如果你的代码包含潜在的运维风险,也不应该允许合并。
我想要一个工具,把这种“资深工程师直觉”形式化为可执行的东西——一个扫描器,它不在乎变量名,但非常关注应用是否能够在部分网络中断的情况下存活。
由于找不到满足我需求的工具,我自己实现了它。
介绍 Production‑Readiness
Production‑Readiness 是一个开源、带有主观倾向的扫描器,旨在在运营盲点进入生产环境之前检测它们。
- 它不是 Prometheus 或 Datadog 的替代品。
- 它是一个预检工具,查找在代码中看似“正确”但在生产环境中会引发故障的模式。
实际捕获了什么?
与标准的 linter 不同,这个工具会查找语义层面的操作模式。以下是一些使用普通正则 grep 难以捕获的规则示例:
1. “悬挂客户端”陷阱
- 风险: 实例化一个带有无限超时的 HTTP 客户端会占用所有线程/协程,最终导致服务崩溃。
- 修复: 扫描器会标记未显式设置超时的客户端初始化。
2. 缺失优雅关闭
- 风险: 当 Kubernetes 缩容 Pod 时,会发送
SIGTERM。如果应用未处理该信号并完成进行中的请求,就会在每次部署或自动伸缩事件中丢失用户流量。 - 修复: 扫描器会检查信号处理的相关代码。
3. 未验证的配置
- 风险: 应用启动需要
API_KEY环境变量。部署后因新环境中缺少该变量而出现 crash‑loop。 - 修复: 扫描器会检查关键配置输入是否配有相应的验证检查。
实际演示
该工具使用 Go 编写,并打包为单个二进制文件,可直接放入任何 CI 流水线中。
$ pr scan ./my-microservice
它会生成一份按优先级排序的运营风险报告。

结论
“能运行的代码”和“在生产环境中可靠运行的代码”之间的差距是巨大的。我们必须停止依赖希望和手动检查清单来弥合这一差距。
通过自动化检测运维反模式,我们可以更快地交付,更重要的是,睡得更安稳。
该项目是开源的,我们才刚刚开始定义软件何为“生产就绪”的规则。
如果你曾因生产环境中一个“愚蠢”的配置错误而吃过亏,试试看吧。
👉 在 GitHub 上给仓库加星