AI会干活 / 免费教程
本地能跑线上翻车前,让 Codex 先查清配置和环境变量
很多“本地正常,线上翻车”的问题,并不是业务逻辑写错,而是改动前没有查清环境差异。你在本地看到功能开关是开的,预发环境却读了另一套默认值;你在开发环境调用的是 mock 服务,生产环境调用的是真实外部接口;你以为缺少环境变量会启动失败,结果代码里悄悄给了一个宽松默认值;你以为配置来自 `.env...
适合人群
担心本地能跑线上翻车的开发者
先解决什么
同一功能在开发、预发、生产环境表现不同。
学完结果
配置风险表和改动前确认清单。
你会学到什么
让 Codex 收集配置读取点、默认值、环境变量名和缺失时的行为。
准备材料:环境变量示例文件、配置目录、部署说明、报错日志。
交付物:配置风险表和改动前确认清单。
边界:重点是环境差异,不讨论业务逻辑本身。
教程定位
这篇教程解决什么问题
很多“本地正常,线上翻车”的问题,并不是业务逻辑写错,而是改动前没有查清环境差异。你在本地看到功能开关是开的,预发环境却读了另一套默认值;你在开发环境调用的是 mock 服务,生产环境调用的是真实外部接口;你以为缺少环境变量会启动失败,结果代码里悄悄给了一个宽松默认值;你以为配置来自 `.env`,实际部署时被平台变量、容器参数或启动脚本覆盖了。
这篇文章讲一个非常具体的 Codex 用法:改功能前,先让 Codex 做一次只读的配置和环境变量审计。目标不是让它解释业务规则,也不是让它直接改代码,而是让它收集这几个事实:配置从哪里读,环境变量叫什么,默认值是什么,缺失时会发生什么,不同环境可能读到哪些不同值,哪些差异会影响你准备改的功能。
最终产物有两份。第一份是“配置风险表”,列出配置项、读取位置、默认值、环境差异、缺失行为和风险等级。第二份是“改动前确认清单”,告诉你在动代码前需要向谁确认、在哪些环境验证、哪些变量不能猜、哪些默认值不能依赖。它尤其适合那些同一功能在开发、预发、生产表现不同的场景。
这里的关键原则是:先查配置,再改功能。不要把环境差异当成业务逻辑问题来修。比如“预发能看到新入口,生产看不到”,可能不是权限判断错了,而是 `FEATURE_NEW_PANEL` 在两个环境取值不同;“本地保存成功,线上报 503”,可能不是接口代码错了,而是本地走 mock,生产走外部服务;“开发环境允许空回调地址,生产环境拒绝”,可能是 `STRICT_CALLBACK_VALIDATION` 默认值被不同启动脚本覆盖。Codex 适合帮你把这些读取点和默认值找出来,但最后的环境取值和上线策略要由人确认。
本文会用一个安全虚构的后台通知功能举例。功能在本地开发环境能正常发送测试通知,预发环境偶尔失败,生产环境上线前存在风险。我们不会使用真实密钥、真实域名、真实邮箱、真实手机号或公司内部数据。样例里的变量名、路径和日志都是演示用途,你可以把方法迁移到支付、登录、回调、消息通知、文件上传、功能开关、缓存、搜索和第三方集成等场景。
使用场景
什么情况下最适合用这一套
你正在改一个后台通知功能。产品希望在“任务状态变更”时给用户发送站内通知,并在某些情况下同步调用外部消息服务。你在本地跑了功能,表单能提交,通知记录能写入,控制台也能看到发送成功。看起来需求很简单:补一个触发条件,改一个展示文案,再加一条测试。
但你心里不踏实,因为这个功能在不同环境的表现不一样:
如果这时候直接让 Codex “帮我改通知逻辑”,它可能会找到业务代码,然后在本地测试下通过。可真正的风险不在那一行业务判断,而在配置读取链路:本地读的是哪个变量,预发读的是哪个变量,生产缺失变量时是报错、降级、使用默认值,还是静默跳过。
这篇教程适合这些开发者:
这套方法不解决业务逻辑本身。例如它不会帮你判断“什么状态应该触发通知”,也不会帮你设计“哪些用户应该收到消息”。它只聚焦环境差异:配置项叫什么,从哪里读取,默认值是什么,缺失时怎样,不同环境需要确认什么。业务规则可以另开一轮审查,但不要和配置审计混在一起。
- 你准备改一个依赖功能开关、外部服务、回调地址、存储桶、队列、缓存或第三方 API 的功能。
- 你发现同一段代码在开发、预发、生产环境表现不同,但还没弄清差异来自哪里。
- 你要改的功能本地能跑,但你担心上线后因为环境变量、部署参数或默认配置翻车。
- 你接手的是一个配置来源很多的仓库:`.env.example`、`config/`、部署说明、Docker Compose、CI 脚本、平台变量、代码默认值都可能参与。
- 你需要在改代码前给同事一份“确认清单”,而不是只说“应该没问题”。
- 本地开发环境使用 `NOTIFY_PROVIDER=mock`,不会真的调用外部服务。
- 预发环境使用 `NOTIFY_PROVIDER=sandbox`,但偶尔报 `missing callback url`。
- 生产环境部署说明里提到 `NOTIFY_PROVIDER=vendor`,还要求配置签名密钥和回调域名。
- `.env.example` 里有 `FEATURE_TASK_NOTIFY=true`,但部署文档写的是 `TASK_NOTIFY_ENABLED`。
- 某个启动脚本里还有 `STRICT_NOTIFY_CHECK=false`,你不知道线上有没有覆盖。
材料准备
开始前先把材料和边界备齐
开始前先收集输入材料。配置审计最怕只给一句“帮我看看环境变量”,因为仓库里可能有几十个变量,Codex 会把数据库连接、日志级别、测试开关、部署端口全都列出来,反而看不到与你这次改动有关的风险。
最少准备五类材料。
第一类是功能范围。用一两句话说明你要改的功能,不需要展开业务细节,只要说明它依赖什么外部条件。例如:“任务状态变更后发送通知,可能依赖通知服务提供商、功能开关、回调地址、签名密钥和队列配置。”
第二类是环境变量示例文件。常见文件包括 `.env.example`、`.env.local.example`、`.env.test`、`apps/api/.env.example`、`config/example.env`。不要把真实 `.env` 里的值贴给 AI,尤其不要贴真实密钥、token、数据库连接串、cookie、内部域名或客户信息。示例文件可以给变量名和安全占位值。
第三类是配置目录。比如 `config/`、`apps/api/src/config/`、`packages/config/`、`settings/`、`deploy/`、`infra/`。这些地方经常定义默认值、环境映射、配置 schema 和启动检查。
第四类是部署说明。包括 README、部署文档、Docker Compose、Kubernetes 示例、CI 工作流、平台变量说明、启动脚本。部署说明里的变量名不一定和代码一致,这正是要查的重点。
第五类是报错日志或现象。只给和这次功能相关的几行,保留错误类型、环境、变量名、服务名、request id 这类结构化信息,去掉真实用户信息和敏感值。比如可以写 `requestId=req_demo_104`,不要写真实手机号、真实邮箱、真实客户名称。
建议你在给 Codex 前先整理成一个“配置调查卡”:
准备时还有一个小技巧:把你怀疑相关的关键词列出来。比如 `notify`、`notification`、`provider`、`callback`、`webhook`、`signing`、`feature`、`queue`、`TASK_NOTIFY`。Codex 可以继续扩展关键词,但你给的起点越准确,它越不容易跑偏。
目标:
改任务通知功能前,请只读审计相关配置和环境变量,不要修改代码。
功能范围:
任务状态变更后发送站内通知,并在特定条件下调用外部通知服务。
已知环境差异:
本地开发环境使用 mock provider。
预发环境偶尔报 missing callback url。
生产部署说明要求 vendor provider、callback url 和 signing secret。
输入材料:
- .env.example
- apps/api/.env.example
- config/notify.ts
- apps/api/src/config
- deploy/README.md
- docker-compose.yml
- 预发脱敏日志片段
本轮产物:
配置风险表和改动前确认清单。
边界:
只读,不改代码,不写入真实环境,不打印真实密钥,不调用外部服务。实操流程
按这套步骤把工作跑起来
第一步,让 Codex 先确认配置来源,而不是直接搜索某个变量。
很多项目的配置不只来自 `.env`。它可能先由启动脚本设置,再被配置库读取,经过 schema 校验,最后注入到业务模块。也可能本地用 `.env.local`,预发用部署平台变量,测试用 `.env.test`,CI 用工作流里的 `env`,Docker Compose 又有一份默认值。
你要让 Codex 先找“配置入口”:项目如何加载环境变量,配置对象在哪里构造,是否使用 `dotenv`、`zod`、`joi`、`convict`、`config`、框架内置 config module,是否有 `loadConfig()`、`getEnv()`、`env.ts`、`settings.py` 这类统一入口。输出时要求它列出文件路径和证据,例如“`apps/api/src/config/index.ts` 调用 `process.env.NOTIFY_PROVIDER`,并在缺失时返回 `mock`”。
第二步,把功能关键词扩展成变量候选。
不要只搜你已经知道的 `FEATURE_TASK_NOTIFY`。同一功能在不同目录里可能叫不同名字:`TASK_NOTIFY_ENABLED`、`ENABLE_TASK_NOTIFICATION`、`NOTIFY_PROVIDER`、`NOTIFICATION_DRIVER`、`WEBHOOK_CALLBACK_URL`、`MESSAGE_QUEUE_NAME`。让 Codex 围绕功能关键词搜索变量读取点、配置字段名、默认值和文档说明。
这一步要把“变量名相似但含义不同”的情况分开。例如 `NOTIFY_PROVIDER` 可能决定使用 mock、sandbox 还是 vendor;`TASK_NOTIFY_ENABLED` 可能只是控制入口显示;`NOTIFY_QUEUE_ENABLED` 可能只影响异步发送;`STRICT_NOTIFY_CHECK` 可能只影响缺失配置时是否启动失败。它们不能被合并成一句“通知开关”。
第三步,追踪每个变量从读取到使用的路径。
找到变量名还不够。你要让 Codex 继续追它被谁使用。一个配置项可能在 config 层读入,在 service 层判断,在 provider 工厂里选择实现,在部署脚本里覆盖。每个变量至少回答六个问题:
例如 `NOTIFY_CALLBACK_URL` 如果缺失,本地 mock provider 可能完全不读取,所以本地不报错;sandbox provider 可能发送前才检查,所以预发偶尔报错;vendor provider 可能启动时就校验,所以生产可能直接启动失败。这个差异比业务代码本身更重要。
第四步,核对示例文件、配置目录和部署说明是否一致。
这是配置审计里最容易发现问题的一步。`.env.example` 可能写 `FEATURE_TASK_NOTIFY=true`,部署说明写 `TASK_NOTIFY_ENABLED=1`,代码里读 `TASK_NOTIFICATION_ENABLED`。三者只差几个词,但足够让生产环境读不到正确值。
让 Codex 做一个对照表:示例文件中出现的变量、代码中读取的变量、部署文档中提到的变量、日志中出现的变量。对每个变量标记状态:
第五步,找出“默认值掩盖风险”的地方。
默认值本身不是坏事,但默认值会掩盖环境差异。最危险的是生产环境缺失关键变量时,代码仍然给出一个看似可用的默认值。例如:
让 Codex 特别标记默认值的来源:是代码硬编码、配置 schema 默认值、示例文件、部署平台默认值,还是测试 fixture。不同来源的可信度不同。代码默认值会真实生效;示例文件只是提示;部署平台默认值要登录平台或问运维确认;测试 fixture 不能当生产事实。
第六步,检查缺失行为和失败时机。
同样是缺少环境变量,风险完全不同。有的项目启动时就校验并失败,这是容易发现的问题;有的项目只在调用某个 provider 时才失败,这是更隐蔽的问题;还有的项目会降级成 mock 或跳过发送,这是最容易造成“本地通过、线上无效果”的问题。
让 Codex 为每个关键变量补一列“缺失行为”:
对上线前的开发者来说,“静默降级”和“行为不明”尤其危险。前者会让你以为功能没问题,后者会让你在生产流量下才知道答案。
第七步,按环境整理差异。
配置审计不能只输出一堆变量。你要让 Codex 站在开发、预发、生产三个环境看同一个功能。最少分成这些列:开发环境来源、预发环境来源、生产环境来源、是否有证据、需要谁确认。
如果 Codex 无法读取真实环境变量,这很正常,也应该如此。它不能凭空断言生产是什么值。它只能根据 `.env.example`、部署说明、CI 文件、容器配置和日志推断“可能差异点”,然后把“需要人工确认”的事项列出来。你要鼓励它说“不确定”,而不是让它编一个确定答案。
第八步,生成配置风险表。
配置风险表建议包含这些字段:
| 配置项 | 作用 | 读取位置 | 默认值 | 缺失行为 | 环境差异线索 | 风险等级 | 改动前确认 | | --- | --- | --- | --- | --- | --- | --- | --- | | `NOTIFY_PROVIDER` | 选择通知服务实现 | `config/notify.ts`、`providerFactory.ts` | `mock` | 静默使用 mock | 本地 mock,生产文档写 vendor | 高 | 确认生产是否显式配置 vendor | | `TASK_NOTIFY_ENABLED` | 控制任务通知是否启用 | `featureFlags.ts` | `false` | 功能关闭 | 示例文件和部署文档变量名不一致 | 高 | 统一变量名并确认三个环境取值 | | `NOTIFY_CALLBACK_URL` | 外部服务回调地址 | `vendorClient.ts` | 无 | sandbox 运行时报错 | 预发日志出现 missing callback url | 中 | 确认预发和生产是否都配置 | | `STRICT_NOTIFY_CHECK` | 是否启动时强校验 | `config/schema.ts` | `false` | 继续启动 | 启动脚本可能覆盖 | 中 | 决定上线前是否打开严格校验 |
表格里的路径和变量名要来自证据,不要写成“应该在某处”。如果只是推断,要在“环境差异线索”或“改动前确认”里写明“需确认”。
第九步,生成改动前确认清单。
清单要足够具体,最好能直接拿去问同事或检查部署平台。不要写“确认环境变量是否正确”这种空话。要写成:
这份清单的目的不是让 Codex 替你做环境变更,而是让你知道上线前要问什么、查什么、验证什么。涉及生产平台、密钥、外部服务和权限变更时,必须由有权限的人确认。
第十步,等配置风险确认后再改功能。
如果风险表里有高风险项,例如代码读取变量名和部署说明变量名不一致,或者生产缺失关键变量会静默降级,不建议马上改业务功能。先把配置口径确认清楚,再进入代码修改。否则你可能改对了逻辑,却上线到一套根本没有启用的环境里。
反过来,如果风险表显示关键变量一致、缺失行为明确、三个环境都有验证路径,你就可以把这份表作为改动说明的一部分。提交代码时附上“本次依赖的配置项”和“已确认环境差异”,比一句“本地已测”可靠得多。
- 变量名是什么?
- 在哪些文件读取?
- 是否有默认值?
- 默认值在开发、测试、生产是否一样?
- 缺失时是抛错、警告、降级、静默使用默认值,还是导致运行时报错?
- 它影响本次功能的哪一部分?
- 一致:示例、代码、部署说明都能对应上。
- 代码读取但示例缺失:新人本地可能不知道要配置。
- 示例存在但代码未读取:可能是废弃变量,也可能是代码路径没搜全。
- 部署说明存在但代码未读取:可能是历史文档,必须人工确认。
- 代码读取变量名和部署说明变量名不一致:高风险,改动前必须确认。
- 缺少 `NOTIFY_PROVIDER` 时默认 `mock`,导致生产静默不发送真实通知。
- 缺少 `STRICT_NOTIFY_CHECK` 时默认 `false`,导致缺少回调地址也能启动。
- 缺少 `NOTIFY_QUEUE_NAME` 时默认使用开发队列名,导致消息进入错误队列。
- 缺少 `VENDOR_TIMEOUT_MS` 时默认 30000,本地没问题,生产请求堆积。
- 启动失败:配置 schema 要求必填,缺失时服务起不来。
- 启动警告:打印 warning,但服务继续运行。
- 运行时报错:调用到相关功能时才报错。
- 静默降级:使用 mock、默认 provider、空回调、跳过发送。
- 行为不明:没找到明确校验,需要人工验证。
- 生产环境是否显式设置 `NOTIFY_PROVIDER=vendor`,而不是依赖默认值?
- 预发和生产使用的是同一个变量名 `TASK_NOTIFY_ENABLED`,还是存在旧变量 `FEATURE_TASK_NOTIFY`?
- `NOTIFY_CALLBACK_URL` 在预发和生产是否都有非空值?回调域名是否是对应环境的域名?
- 缺少 `NOTIFY_SIGNING_SECRET` 时服务是否启动失败?如果不是,是否需要在上线前改成强校验?
- 本地测试是否覆盖 `mock` provider,预发验证是否覆盖 `sandbox` provider,生产发布前是否有只读健康检查?
- 部署说明、`.env.example`、配置 schema 是否需要同步更新,避免下一个人继续用错变量名?
输入示例
可以直接参考的输入材料
下面是一段可以交给 Codex 的安全虚构材料。它保留了真实排查需要的结构,但没有真实密钥、真实域名、真实邮箱、真实手机号或公司隐私。
如果你担心 Codex 误把测试配置当成生产配置,可以额外补一句:“请区分示例文件、测试 fixture、开发默认值和生产部署说明,不要把测试值当作线上事实。”
目标:
请只读审计任务通知功能相关的配置和环境变量。不要改代码,不要安装依赖,不要启动服务,不要调用外部接口。
功能范围:
任务状态从 pending 变为 done 时,系统会创建站内通知;如果开启外部通知 provider,还会调用外部消息服务。
已知环境差异:
- 本地开发环境可以正常保存任务和创建通知记录。
- 预发环境偶尔报 missing callback url。
- 生产部署说明里提到 provider 必须是 vendor,且需要 callback url 和 signing secret。
我能提供的文件线索:
- .env.example
- apps/api/.env.example
- config/notify.ts
- apps/api/src/config/index.ts
- apps/api/src/modules/notification
- deploy/README.md
- docker-compose.yml
- .github/workflows/deploy-preview.yml
脱敏日志:
[2026-06-20T09:14:11.239Z] env=staging requestId=req_demo_721 module=notification error="missing callback url" provider=sandbox
[2026-06-20T09:14:11.251Z] env=staging requestId=req_demo_721 action=sendTaskNotification status=failed
.env.example 片段:
FEATURE_TASK_NOTIFY=true
NOTIFY_PROVIDER=mock
NOTIFY_CALLBACK_URL=http://localhost:3000/demo-callback
STRICT_NOTIFY_CHECK=false
deploy/README.md 片段:
Production required variables:
TASK_NOTIFY_ENABLED=1
NOTIFY_PROVIDER=vendor
NOTIFY_CALLBACK_URL=<set in deployment platform>
NOTIFY_SIGNING_SECRET=<set in secret manager>
请输出:
1. 配置来源和读取链路。
2. 相关环境变量对照表。
3. 默认值和缺失行为。
4. 开发、预发、生产差异线索。
5. 配置风险表。
6. 改动前确认清单。提示词
可复制使用的提示词
下面这段可以直接复制使用。把方括号里的内容换成你自己的材料即可。
如果你是在一个多人协作仓库里使用,还可以加一句:“本轮只做审计,不修改任何文件;如果发现问题,先列出建议,不要直接改。”
你是一个只读配置审计助手。请不要修改代码、不要安装依赖、不要启动长期进程、不要调用外部服务、不要读取或输出真实密钥值。你的任务是在我改功能前,查清相关配置和环境变量,重点关注开发、预发、生产环境差异。
我要改的功能:
[用一两句话说明功能范围,只写和配置相关的依赖,例如功能开关、provider、回调地址、队列、缓存、存储桶、第三方服务]
已知异常或担忧:
[写本地、预发、生产表现差异;粘贴脱敏报错日志;不要粘贴真实 token、cookie、手机号、邮箱、客户名称]
输入材料:
[列出 .env.example、配置目录、部署说明、CI 文件、Docker Compose、相关模块路径、日志片段]
请按以下步骤只读检查:
1. 找到项目加载配置和环境变量的入口,列出文件路径和证据。
2. 围绕功能关键词搜索相关变量名、配置字段、默认值和文档说明。
3. 对每个变量追踪:读取位置、使用位置、默认值、缺失行为、影响功能。
4. 对照示例文件、代码读取点、部署说明、CI/容器配置,找出变量名不一致、示例缺失、代码未读取、文档过期等问题。
5. 区分开发、测试、预发、生产线索;无法确认真实环境值时请明确写“需要人工确认”,不要编造。
6. 标记默认值掩盖风险,尤其是缺失变量后静默使用 mock、跳过功能、连接错误环境、使用开发队列的情况。
7. 输出一张配置风险表,字段包括:配置项、作用、读取位置、默认值、缺失行为、环境差异线索、风险等级、改动前确认。
8. 输出一份改动前确认清单,要求每一项都能被人工检查或询问负责人。
输出要求:
- 不讨论业务逻辑是否正确,只讨论配置和环境差异。
- 所有结论都要带文件路径、变量名、日志或文档证据。
- 对推断内容标注“推断”或“需确认”。
- 不要输出真实密钥值;如果看到疑似密钥,只写变量名和“值已省略”。输出样例
AI 应该输出到什么程度
下面是一次理想输出的缩略样例。真正项目里路径和变量会更多,但结构应该类似。
这个输出好在三点:它没有替你猜生产真实值;它把变量名不一致和默认值风险放到了高风险;它没有讨论任务状态变更的业务规则,而是牢牢围绕配置和环境差异。
配置审计结论:本轮只读检查发现 4 个与任务通知相关的关键配置项,其中 2 个存在上线前高风险确认项。
一、配置来源
- apps/api/src/config/index.ts
证据:统一读取 process.env,并导出 appConfig。
- config/notify.ts
证据:构造 notifyConfig,包含 provider、callbackUrl、strictCheck。
- apps/api/src/modules/notification/providerFactory.ts
证据:根据 notifyConfig.provider 选择 mock、sandbox、vendor provider。
- deploy/README.md
证据:生产部署说明列出 TASK_NOTIFY_ENABLED、NOTIFY_PROVIDER、NOTIFY_CALLBACK_URL、NOTIFY_SIGNING_SECRET。
二、变量对照
| 配置项 | 代码读取 | 示例文件 | 部署说明 | 状态 |
| --- | --- | --- | --- | --- |
| 任务通知开关 | TASK_NOTIFY_ENABLED | FEATURE_TASK_NOTIFY | TASK_NOTIFY_ENABLED | 高风险:示例变量名与代码/部署不一致 |
| 通知 provider | NOTIFY_PROVIDER | NOTIFY_PROVIDER | NOTIFY_PROVIDER | 一致,但默认值为 mock |
| 回调地址 | NOTIFY_CALLBACK_URL | NOTIFY_CALLBACK_URL | NOTIFY_CALLBACK_URL | 一致,预发日志显示缺失 |
| 签名密钥 | NOTIFY_SIGNING_SECRET | 未出现 | NOTIFY_SIGNING_SECRET | 高风险:生产要求但示例缺失 |
三、配置风险表
| 配置项 | 作用 | 读取位置 | 默认值 | 缺失行为 | 环境差异线索 | 风险等级 | 改动前确认 |
| --- | --- | --- | --- | --- | --- | --- | --- |
| TASK_NOTIFY_ENABLED | 控制任务通知是否启用 | apps/api/src/config/index.ts | false | 功能关闭 | .env.example 使用 FEATURE_TASK_NOTIFY | 高 | 确认开发、预发、生产统一使用 TASK_NOTIFY_ENABLED |
| NOTIFY_PROVIDER | 选择 provider | config/notify.ts | mock | 静默使用 mock | 本地示例为 mock,生产文档为 vendor | 高 | 确认生产显式配置 vendor,避免默认 mock |
| NOTIFY_CALLBACK_URL | 外部回调地址 | config/notify.ts、vendorClient.ts | 无 | sandbox/vendor 发送时运行时报错 | 预发日志 missing callback url | 中 | 确认预发和生产都配置对应环境 URL |
| NOTIFY_SIGNING_SECRET | 外部通知签名 | vendorClient.ts | 无 | vendor 调用时失败,启动不失败 | 生产文档要求,示例缺失 | 高 | 确认密钥由密钥管理注入,并考虑启动强校验 |
四、改动前确认清单
1. 生产是否显式设置 NOTIFY_PROVIDER=vendor,而不是依赖默认值?
2. 三个环境是否统一使用 TASK_NOTIFY_ENABLED?是否需要清理 FEATURE_TASK_NOTIFY?
3. 预发 missing callback url 是否来自 NOTIFY_CALLBACK_URL 缺失,还是 provider 配置读取顺序问题?
4. NOTIFY_SIGNING_SECRET 缺失时是否应该在启动阶段失败,而不是发送时失败?
5. 本次功能测试是否覆盖 mock、sandbox、vendor 三种 provider 的差异?
6. .env.example、部署说明、配置 schema 是否需要同步更新?
五、仍需人工确认
- 无法从仓库确认生产平台真实变量值,需要部署负责人确认。
- 无法确认密钥是否已在密钥管理中配置,Codex 不应读取或输出真实值。
- 预发日志只显示 missing callback url,不能证明生产也缺失,只能作为风险线索。人工验收
人要怎么检查和改到可用
Codex 输出配置风险表后,人要做复核。配置和环境变量属于“证据必须落地”的领域,不能只因为 AI 找到一个文件就认为事实成立。
第一,打开关键文件确认读取点。重点看 Codex 是否把测试配置、示例配置或旧代码当成线上配置。比如 `config/notify.test.ts` 里的默认值不能代表生产;`deploy/README.old.md` 里的变量名可能已经过期;`docker-compose.yml` 里的本地变量也不一定会进入云端部署。
第二,确认变量名是否真的一致。变量名大小写、前缀、下划线差一点都会导致读取失败。尤其要检查这些组合:代码读取 `TASK_NOTIFY_ENABLED`,示例写 `FEATURE_TASK_NOTIFY`;代码读取布尔字符串 `"true"`,部署文档写 `1`;代码要求 `NOTIFY_PROVIDER=vendor`,部署脚本传入 `notification-vendor`。这些不是业务逻辑问题,而是环境口径问题。
第三,确认默认值是否适合生产。开发环境默认 `mock` 很合理,生产环境默认 `mock` 就很危险。你可以把默认值分成三类:开发友好默认值、测试专用默认值、生产必须显式配置。凡是涉及外部服务、签名密钥、回调地址、生产队列、真实存储桶的变量,都不应该靠模糊默认值上线。
第四,确认缺失行为。最好本地用安全方式模拟缺失变量,看服务是启动失败、打印警告、运行时报错还是静默降级。这个动作不要连真实外部服务,也不要写生产数据。目标只是验证代码路径,比如运行配置校验测试、读取配置对象、调用 mock provider 的初始化逻辑。
第五,确认不同环境的真实取值。Codex 通常不能也不应该读取生产平台的真实变量。你需要找部署负责人、运维同事或平台控制台确认。确认时不要把密钥值贴回聊天,只需要确认“变量存在、来源正确、环境匹配、最近部署已生效”。
第六,决定是否需要先修配置口径。配置审计可能发现两类改动:一种是文档或示例文件缺失,另一种是代码缺少强校验。前者可以随功能改动一起补;后者要谨慎,因为把缺失变量从“运行时报错”改成“启动失败”可能影响现有部署流程。涉及生产启动行为、密钥注入、部署配置的改动,不要顺手改,先和负责人确认。
第七,把风险表放进改动说明。你可以在提交说明、评审描述或上线单里写清楚:本次功能依赖哪些变量,哪些环境已确认,哪些变量不读取真实值但确认存在,哪些默认值只用于本地。这样评审者看到的不是“本地测过”,而是“环境差异已经被查过”。
人工修改时要遵守一个边界:不要为了让本地测试通过,把生产需要的变量写死到代码里,也不要把真实密钥放进 `.env.example`、测试 fixture、文档或提交记录。示例文件只放安全占位值,例如 `<set in secret manager>`、`http://localhost:3000/demo-callback`、`demo_queue`。真实值只能留在本地密钥文件、密钥管理系统或部署平台变量里。
失败反例
这些失败反例要提前避开
反例一:只让 Codex 搜一个变量名,漏掉同义变量。
你问:“帮我看看 `FEATURE_TASK_NOTIFY` 有没有问题。”Codex 搜到 `.env.example` 里有这个变量,前端某处也引用过,于是输出“通知功能开关存在”。但后端实际读取的是 `TASK_NOTIFY_ENABLED`,生产部署说明也写这个新变量。结果你改完本地功能,生产仍然没启用,因为真正生效的变量从来不是你搜的那个。
正确做法是让 Codex 从功能关键词扩展变量候选,并对照示例文件、代码读取点、部署说明和日志。不要把第一个搜到的变量当成唯一真相。
反例二:把本地 `.env.example` 当成生产事实。
你看到 `.env.example` 里写 `NOTIFY_PROVIDER=mock`,就以为生产也可以用 mock 路径测试。Codex 如果没有被要求区分环境来源,也可能把示例文件里的值写进结论。实际上 `.env.example` 只是给开发者本地启动用,生产变量来自部署平台,provider 应该是 `vendor`。
正确做法是要求 Codex 标记每个值的来源:示例文件、代码默认值、测试配置、部署文档、CI、容器参数或日志。只有代码默认值和实际部署变量会影响运行,示例值不能代表线上。
反例三:忽略缺失变量时的静默降级。
你只检查了“有没有读取 `NOTIFY_CALLBACK_URL`”,发现代码里确实读取了,于是认为安全。上线后才发现缺少这个变量时,mock provider 不报错,sandbox provider 发送时报错,vendor provider 则跳过外部通知但仍返回成功。表面看请求成功,实际通知没有发出去。
正确做法是让 Codex 对每个关键变量输出“缺失行为”和“失败时机”。只知道变量名不够,必须知道缺失时是启动失败、运行时报错、警告、降级还是静默跳过。
反例四:把配置问题误判成业务逻辑问题。
预发环境没有出现任务通知,你让 Codex 直接检查“状态变更是否触发通知”。它改了业务条件,让更多状态进入发送逻辑。本地测试通过,但预发仍然没有通知,因为真正的问题是 `TASK_NOTIFY_ENABLED=false`。这类修法会把代码变复杂,却没有碰到根因。
正确做法是先查环境差异,再查业务逻辑。只要现象是“同一功能在不同环境表现不同”,第一轮就应该优先做配置和环境变量审计。
反例五:让 Codex 输出或保存真实密钥。
有些开发者会把真实 `.env` 贴给 AI,甚至让它整理成表格。这样会把密钥暴露在聊天记录、草稿、日志或提交中。即使 Codex 没有恶意,这也是错误流程。
正确做法是只给变量名和安全占位值。看到疑似真实密钥时,应要求 Codex 只记录变量名和用途,不复制值,不写入文档,不放进测试。
主题边界
它和相邻主题的区别
这篇文章只讨论改功能前的配置和环境变量审计。它和几个相邻主题很容易混淆,需要分清。
它不同于“从代码里挖业务规则”。业务规则审查关注的是条件、权限、计费、状态流转和影响模块,问题是“系统为什么这样判断”。配置审计关注的是环境差异,问题是“同一段代码在不同环境会读到什么配置”。如果你要判断“哪些状态应该触发通知”,那是业务规则;如果你要判断“通知功能在生产有没有启用”,那是配置审计。
它不同于“从页面追接口链路”。接口链路追踪关注 URL、组件、hook、API client、后端 handler 和数据源,问题是“请求从哪里到哪里”。配置审计关注 provider、开关、默认值、部署变量和缺失行为,问题是“请求走哪条路径取决于哪些环境配置”。一个接口 500 可能需要追链路,但如果只有预发 500、本地不复现,先查配置更稳。
它不同于“改表单字段前追数据流”。字段流转关注 UI 字段、请求体、DTO、数据库列、导出和回显,问题是“字段经过哪些层”。配置审计关注环境变量和配置文件,问题是“这些层在不同环境是否启用同一套行为”。字段链路讲的是数据形态,配置审计讲的是运行条件。
它也不同于“上线前检查清单”。上线检查可能包括测试、回滚、监控、灰度、负责人、发布时间和用户通知。本文只覆盖其中一小块:与本次功能相关的配置风险。你可以把本文产出的风险表放进上线检查,但不要把它当成完整发布流程。
最后再强调一次:当你遇到“开发、预发、生产表现不同”时,不要急着改业务逻辑。先让 Codex 查清配置读取点、默认值、环境变量名和缺失时的行为。只要这一步做扎实,很多看起来玄学的线上问题,都会变成一张可以逐项确认的表。
可直接套用的流程
1. 先写清楚任务目标:这次要让 AI 帮你完成什么工作,而不是泛泛地问一个问题。
2. 再给资料边界:哪些背景、数据、约束、口径必须被使用,哪些内容不能编。
3. 最后规定输出格式:用清单、表格、方案、话术还是复盘报告,并保留人工检查。