# 协作约定(给 AI 助手 / 协作者) > 用户明确表达过的偏好,加上**已经用事故买来的教训**。每次在这个仓库里干活前先读一遍。 > 每条都对应一个真实踩过的坑 —— 删之前先确认那个坑不会再犯。 ## 1. 分支与提交 - `main` = **已发布**(生产跑的就是它)。功能开发**从 main 开分支**: `git checkout -b feat/<功能名> main`,做完合回 `main`。 - `dev` 是**历史工作分支,已与 main 分叉**(dev 上有未上线的账号自动分配功能)。 ⚠️ 旧的「推完 main 再 `dev merge --ff-only main`」约定**已作废** —— 分叉后这么做会失败;以后要同步 dev 只能真合并,并且必须显式确认。 - **不要改一点就提交、推送。** 小改动先攒着、攒够一批再提交;只有用户明确说 「提交 / 推送」,或到了一个自然的里程碑(一个完整功能做完、一轮反馈全部改完) 才 commit / push。一次提交要**整合**相关改动,别拆成一堆碎提交。 - 远端名不统一:本地是 `gitea`,生产服务器上的同一个仓库叫 `origin`(URL 相同)。 ## 2. 功能改动 - **新功能是「增加」,不是「替换」。** 旧路径要完整保留(例:账号检测保留了手动粘贴, 新增「按账号选择」;旧的手动输入逻辑一行未动)。做新功能时先想清楚**旧路径会不会被影响**, 需要扩展的地方用**可选参数 / 并集**,不要改默认行为。 - 改动要**务实、克制**:不做没人要的重构,不加用不上的抽象。 - **不要重复展示同一份数据。** 数据库里已有的字段(如 `accounts.points` / `gold_balance` / `elite_opened`)就让已有界面显示,查询去**刷新**它们,不要另开一份副本 —— 同一屏两份会让人分不清哪份是准的。 - **单项外部调用失败不要让整个流程失败**,但要**如实暴露**(错误写进 `errors` / 返回值 并在 UI 展示),别让「没查到」被读成「没有」。 - 旁路动作(写事件、写审计、释放资源)**绝不能带崩主流程**:单独 try/except + 记 warning, 但要留兜底(如定时作业)把漏掉的补上。 ## 3. 验证要求(怎么证明你做对了) - **结论要有验证**:能实测就实测(有生产镜像库 `douyu_login_prod` 可只读查), 关键是**反向验证** —— 把 bug 注入回去,确认用例真的会变红,再还原。 「跑了一下没报错」不算验证。 - **提交/推送会跑钩子**,所以本地必须按同样标准自查: - `pre-commit`:`ruff format --check`(**只跑 `ruff check` 不够**,格式不对会直接拦下提交) + 前端 `tsc -b`; - `pre-push`:上面这些 + **全量 pytest**。 - **断言要看 `model_dump()`(序列化结果)**,只看属性会假绿(原因见坑 #2)。 - **别信「测试通过」** —— 用例可能是假绿的(原因见坑 #3)。 ## 4. 数据库与迁移 - 迁移编号**按落地顺序取,不预留**;**已应用的迁移不能改名**。 - 加列/加表后,**测试库不会自己长出新结构** —— `tests/support/db.py` 用的是 `Base.metadata.create_all`,它**只建缺失的表,不会 ALTER 已有表**。 症状是 `Unknown column`,处理办法:重建测试库(DROP/CREATE `douyu_login_test`)。 - **本地 `dev.sh` 在跑时,改迁移文件会被它自动应用到你正在用的库**。 所以切分支前先确认「库的迁移版本 == 目标分支的 head」,否则应用会因为 alembic 找不到 revision **直接起不来**(`run_migrations` 没有兜底,会带崩 lifespan)。 - 本地库:`douyu_login`(dev)、`douyu_login_test`(测试,**不要**拿别的库跑测试套件)、 `douyu_login_prod`(生产镜像)。 另有 `douyu_login_prodclone`(停在 `20261003_0040`)与 `douyu_login_rehearsal` (停在 `20261004_0049`):是 S1–S7 上线演练留下的**生产克隆快照**(各 15,182 账号), 代码里没有任何引用 —— 只读参考,别当测试库用。 ## 5. 部署与生产 生产:SSH 别名 `order+douyu_huya`,目录 `/root/live-hub-py`,跑的就是 `main`。 **完整清单见 `docs/上线清单-S1-S7部署.md`**,核心步骤: ```bash # ① 部署前(缺一不可):备份 + 采基线 docker exec live-hub-py-mysql-1 sh -c 'mysqldump ... douyu_login' | gzip > /root/backup_$(date +%m%d_%H%M).sql.gz gzip -t /root/backup_*.sql.gz # 采 CK 基线:样本解密长度 + 持有 CK 账号数(部署后要一字不差地对比) # 查在途任务:正在跑的批次会被重启打断,先看能不能等 # ② 执行:先停 → 再迁移 → 再起 docker compose stop douyu-login docker compose run --rm -T douyu-login alembic upgrade head