「本地能跑、CI 不能跑」十次里有八次是环境变量。它们不会一起报错,而是一个一个让行为变形。 演示七项里三项必填。 最隐蔽的是「无人值守」那个标记:不设它,程序会以为有人坐在那儿,然后等一个不会来的回答。
上一节讲上下文怎么传,这一节讲环境怎么配。 这一节的东西可以直接当清单用——贴进仓库的 README,比记在某个人的脑子里有用。
一、七个变量的分工
必填三项:认证的密钥、标记无人值守的开关、工作目录。 可选一项:往 PR 写评论的令牌。不设也能跑,只是审查结果贴不上去。 建议三项:成本护栏、关彩色输出、时区。不设不会失败,但会让日志难读、账单难算。
这份清单的价值不在「全」,在于它把「必须」和「建议」分开了——不分的话,人会把七项都当成必填。
二、真跑:什么都没设会怎样
演示里第一份环境什么都没设,检查器退出码 1,报三项缺失、两项建议。 第二份按清单补齐必填,退出码 0,只剩两条建议。 要注意的是:检查器只报了 missing,而真实的后果比「缺一个变量」隐蔽得多。
比如少了无人值守那个标记,程序会以为有人坐在那儿,于是等一个永远不会来的回答。
三、性能调优的三类参数
并发:同时跑几个。设太大反而慢——抢 CPU、撞文件、互相等锁。 超时:多久算失败。设太长失败发现得晚,设太短大仓库永远超时。 重试:失败几次再算失败。对幂等步骤有用,对「改了代码」的步骤有害。
第三条最容易被忽略:重试一个已经改过文件的步骤,会把改动做两遍。
四、MCP 在 CI 里的两条规矩
第一,只连只读的。CI 里没人看着,写权限的服务器一旦用错,后果直接进仓库。 第二,密钥从环境变量来。这和第 6.4 节那条是同一条规矩,只是换了个执行环境。 还有一条隐含的:CI 里的 MCP 服务器要能「无状态启动」——不能依赖上一次的会话。
因为每一次流水线都是新机器,任何「本地缓存」都不存在。
五、清单的用法
贴进仓库 README,或者做成一个 .env.example,和代码放一起。 这样新人的第一个 PR 就会照它配,而不是来问你「为什么我这儿跑不起来」。 更好的做法是让检查器进流水线:缺必填就红,别等跑到一半才失败。
这条和 5.11 节那个第一判据是一路的:能自动查的,别靠人记。
六、动手 Demo:七个环境变量,缺哪个会让流水线悄悄跑歪
「本地能跑、CI 不能跑」十次里有八次是环境变量。 这里真跑两份环境:一份什么都没设,一份按清单补齐必填。
MUST = [u"API_KEY", u"CI", u"WORKDIR"]
WARN = [u"MAX_TURNS", u"NO_COLOR"]
miss = [k for k in MUST if not os.environ.get(k)]
sys.exit(1 if miss else 0)
实跑输出:
--------------------------------------------------------------------
七个环境变量,缺哪个会让流水线悄悄跑歪
--------------------------------------------------------------------
「本地能跑、CI 不能跑」十次里有八次是环境变量。
它们不会一起报错,而是一个一个地让行为变形。
① 七个变量的分工
--------------------------------------------------------------------
| 变量 | 干什么 | 必不必填 | 不设会怎样 |
|---|---|---|---|
| API_KEY | 认证 | 必填 | 起不来,报鉴权失败 |
| CI | 标记无人值守 | 必填 | 它会等交互输入,一直挂到超时 |
| WORKDIR | 工作目录 | 必填 | 相对路径全飘,找不到配置 |
| GH_TOKEN | 往 PR 写评论 | 可选 | 只读不写,审查结果贴不上去 |
| MAX_TURNS | 成本护栏 | 建议 | 跑到超时才停 |
| NO_COLOR | 关彩色 | 建议 | 日志里全是转义符,grep 不到关键字 |
| TZ | 时区 | 建议 | 日志时间和别处对不上 |
② 真跑:两份环境,一份缺三项
--------------------------------------------------------------------
什么都没设:退出码 1
missing: API_KEY
missing: CI
missing: WORKDIR
recommend: MAX_TURNS
recommend: NO_COLOR
result: 3 missing, 2 recommended
按清单补齐必填:退出码 0
recommend: MAX_TURNS
recommend: NO_COLOR
result: 0 missing, 2 recommended
第一份漏了 CI 这个变量,检查器只报了 missing,但真实后果更隐蔽:
程序会以为有人坐在那儿,于是等一个永远不会来的回答。
③ 性能调优的三类参数
--------------------------------------------------------------------
| 类别 | 调什么 | 注意什么 |
|---|---|---|
| 并发 | 同时跑几个 | 设太大反而慢:抢 CPU、撞文件 |
| 超时 | 多久算失败 | 设太长,失败发现得晚;设太短,大仓库永远超时 |
| 重试 | 失败几次再算失败 | 对幂等步骤有用,对「改了代码」的步骤有害 |
第三条最容易被忽略:重试一个已经改过文件的步骤,会把改动做两遍。
④ MCP 在 CI 里的两条规矩
--------------------------------------------------------------------
第一,只连只读的。CI 里没人看着,写权限的服务器一旦被用错,后果直接进仓库。
第二,密钥从环境变量来。这和第 6.4 节那条是同一条规矩,只是换了个执行环境。
⑤ 清单的用法
--------------------------------------------------------------------
把这张表贴进仓库的 README,比写在某个人的笔记里有用。
新人的第一个 PR 就会照它配,而不是来问你「为什么我这儿跑不起来」。
! 变量名是示意,实际以各版本文档为准;这里讲的是每一类变量为什么必须有。
①七项分三档:必填三项(密钥、无人值守标记、工作目录)、可选一项(写 PR 评论的令牌)、 建议三项(护栏、关彩色、时区)。 ②什么都没设时退出码 1,报三项缺失、两项建议;补齐必填后退出码 0,只剩两条建议。 ③最隐蔽的是少了「无人值守」那个标记:检查器只报 missing,但真实后果是程序以为有人坐在那儿, 于是等一个永远不会来的回答。 ④调优三类:并发(设太大反而慢、撞文件)、超时(太长发现得晚、太短永远超时)、 重试(对幂等步骤有用,对「改了代码」的步骤有害)。 重试那条最容易被忽略:重试一个已经改过文件的步骤,会把改动做两遍。
30 秒实验
- 把「建议」那三项也提到必填,重跑一遍。第一份环境的退出码变了吗?把建议当必填的代价是什么?
- 给检查器加一条「工作目录必须存在」,重跑一遍。这条检查和「变量有没有设」差在哪一类问题上?
- 把重试加上「最多两次」,然后想一下:哪一类步骤重试是安全的,哪一类不是?
常见误区
- 不设无人值守标记。程序以为有人在,等着一个不会来的回答,一直挂到超时。
- 把七项全当必填。人会挑着填,最后连真的必填项也漏了。
- 用相对路径当工作目录。钩子和脚本的工作目录未必是项目根,相对路径会飘。
- 给「改了代码」的步骤配重试。重试会把改动做两遍,第二次可能直接冲突。
- 以为环境变量是运维的事。它决定了模型在 CI 里的行为,是配置的一部分。
自测三问(点开对答案)
1. 哪三项是必填的? —— 认证密钥、标记无人值守的开关、工作目录。 前者不设起不来,中者不设会挂到超时,后者不设相对路径全飘。 2. 为什么「无人值守」这个标记最隐蔽? —— 因为它不设的时候不报错。程序会以为有人坐在那儿,然后等一个永远不会来的回答,表现为「超时」。 3. 哪一类步骤不能配重试? —— 会改文件的步骤。重试会把改动做两遍,第二次可能直接冲突或者覆盖。清单有了,下一节换成另外两个平台:同一套命令,壳要重包一遍。
- ☐ (本篇完,下一篇 7.9 跨平台 CI/CD 集成)
相关笔记
- 配置详解:密钥不该写进配置
- 跨平台 CI/CD 集成:三个平台的写法对照
- Claude Code 橙皮书 · 索引
- 🐎 Claude Code 实战 · 索引