项目地基:版本、环境与发布
在功能变多前建立代码版本、环境变量和可回滚发布的最小规则。
项目地基不会直接带来用户,但缺少它时,每次修改都会变成一次赌博。
第一版不需要复杂的自动化流水线。需要的是知道三件事:
改了什么、在哪里运行、失败怎么退回。
代码必须进入版本库
至少做到:
- 主分支始终对应一个可以构建的版本
- 一个提交只表达一个清晰变化
- 密钥、数据库文件和本地缓存不进入版本库
- 发布版本能对应到提交编号
- 修改前先看工作区,避免覆盖过去未完成的改动
AI 可以大量改文件,但不能替你判断哪些改动属于同一个提交。
用 AI 写代码时这条尤其重要:一次对话可能改了七个文件,其中三个是你要的功能、两个是顺手的重构、两个是它自己的偏好。全部混在一个提交里,出问题时你没法只回退一部分。
小做法:每次让 AI 改完,先自己过一遍改动清单再提交。 不认识的改动当场问清楚或撤掉。
分开三类配置
| 类型 | 示例 | 放置位置 |
|---|---|---|
| 公开构建配置 | 站点地址、公开统计标识 | 构建参数或公开环境变量 |
| 服务端秘密 | 数据库地址、支付密钥、邮件密码 | 服务器密钥或受控环境变量 |
| 业务配置 | 价格、额度、开关 | 数据库或受版本管理的配置 |
提供一份示例配置文件,只列变量名和填写说明,绝不放真实值。
变量缺失时应尽早报出可理解的错误,而不是等用户付款后才失败。
第三类最容易出事:把价格和额度写进代码。
改一次价要重新发布一次,而且不同环境很容易不一致——测试环境改了、生产忘了改,或者反过来,生产上跑着一个测试用的价格。
价格、额度、开关这类会变的业务参数,放在数据库或独立配置里,改完不用重新部署。
区分开发、预演和生产
开发服务器通过,不代表生产可用。至少保留两种环境:
- 本地开发:允许调试输出和测试账号
- 生产环境:真实域名、真实数据库、严格权限、正式回调地址
如果没有独立预演环境,就在本地完整运行生产构建产物,测试路由、静态文件、登录、回调和环境变量。不要只用开发模式验收。
开发模式和生产构建的常见差异:路由行为不同、静态资源路径不同、环境变量注入时机不同、错误提示详细程度不同。这几处是"本地好的、上线就坏"的主要来源。
发布必须能回滚
一次安全发布至少留下:
- 发布对应的提交编号
- 上一个可运行镜像或构建产物
- 数据库变更和兼容说明
- 发布后的关键页面检查结果
- 出现什么现象时立即回滚
第五条要提前写死,比如"支付回调失败率超过一定比例"或"首页打不开"。事后判断,你会倾向于先修一下试试,而那通常会把小事故拖成长事故。
数据库变更分三步走
数据库变更尽量按这个顺序:
1. 先加新字段,保持旧代码仍能运行
2. 发布新代码,同时兼容新旧两种情况
3. 确认稳定后,再清理旧字段把"改字段"和"立刻要求所有代码使用新字段"放在一步里,回滚会很困难——代码退回去了,数据结构却退不回来。
删字段和改字段名是最危险的两种变更。第一版最好的策略是只加不删,等确实需要清理时再单独做一次。
备份策略见数据库与备份。
建立最小发布清单
- 工作区没有不明改动
- 类型检查和生产构建通过
- 密钥未进入提交和日志
- 数据库有可验证备份
- 上一版本仍可恢复
- 发布后检查主页、主路径、支付与 404
- 记录发布时间和提交编号
"可验证备份"的意思是你真的恢复过一次。没恢复过的备份不算备份,它只是一个你希望有用的文件。
密钥进过版本库怎么办
改掉它不够,因为历史记录里还在。正确做法是:
- 立刻在服务商那边作废这个密钥,重新生成一个
- 然后再清理代码和历史
顺序不能反。只清理历史但不换密钥,等于什么都没做——密钥已经泄露过一次,任何人可能已经拿到了。
常见错误
AI 改完直接提交。 七个文件混在一起,没法部分回退。
密钥进了版本库只改代码不换密钥。 泄露已经发生了。
价格写在代码里。 改价要发版,环境容易不一致。
只用开发模式验收。 本地好的上线就坏。
数据库改字段和改代码一起发。 回滚回不去。
备份从没恢复过。 需要时才发现不可用。
回滚条件没提前定。 事故中倾向于"再修一下试试"。
发布不记提交编号。 出问题时不知道该退到哪。
验收标准
- 主分支始终可构建,一个提交一个变化
- 密钥和本地文件不在版本库里,有示例配置文件
- 价格、额度、开关放在配置或数据库里,改完不用发版
- 验收用过生产构建产物,不只是开发模式
- 数据库变更按"先兼容、后清理"分步做
- 备份真的恢复过一次
- 写下了触发回滚的具体现象
- 发布清单每条都能勾完,含提交编号记录
本章动作
为当前项目完成一次"构建但不发布"的演练,并写下恢复上一版本的准确命令或操作路径。如果回滚只能依靠记忆,地基还没有完成。