diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index 4d59a6e..0000000 --- a/AGENTS.md +++ /dev/null @@ -1,125 +0,0 @@ -# 协作约定(给 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)。 -- **`main` 与 `dev` 的迁移链已经分叉成两个 head**(共同祖先是 `20261008_0052`): - `main` 走 `20261015_0053` → … → `20261107_0067`,`dev` 走 `20261008_0053`(账号租约)。 - 两个 0053 的 **revision id 不同**,所以 alembic 不会报「重复 revision」, - 而是报 **Multiple head revisions are present** —— 合并 `dev` 时必须先补一个 - `alembic merge` 节点,否则 `alembic upgrade head` 会直接失败(部署会卡在迁移那一步)。 - 顺带:本地 `douyu_login` 现在停在 `main` 的 head,**切到 dev 分支前必须先回退/重建库**。 -- 本地库:`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/README.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 账号数(部署后要一字不差地对比) -# 查在途任务:正在跑的批次会被重启打断,先看能不能等 - -# ② 执行:先停 → 再迁移 → 再起(镜像重建过就必须 --force-recreate + 服务名) -docker compose stop douyu-login -docker compose run --rm -T douyu-login alembic upgrade head `(**必须带服务名**,不带会把 mysql 一起重建);部署后**核对镜像 ID**:`docker inspect -f '{{.Image}}' <容器>` 要等于 `docker images --no-trunc` 里 latest 的 ID,或直接 `grep` 容器内新增的函数/文案 | - -## 8. 仓库事实(速查) - -| | | -| --- | --- | -| 分支 | `main` = 已发布(生产跑它);`dev` = 已分叉的历史工作分支;新功能从 main 开 `feat/*` | -| 生产 | SSH `order+douyu_huya`(47.114.114.225),目录 `/root/live-hub-py`,容器 `live-hub-py-douyu-login-1` | -| 本地服务 | `./dev.sh`(8800 端口,`--reload`);**启动时会自动跑迁移** | -| 本地 MySQL | 容器 `live-hub-py-mysql-1`,端口 3307;库见 §4 | -| 生产镜像库 | `douyu_login_prod`(`scripts/refresh_local_prod_mirror.sh` 同步,只读用) | -| 迁移 head | `main` = `20261107_0067`;`dev` = `20261008_0053`(**已经分叉成两个 head**,见 §4) | -| 前端 | `tsc -b` 开了 `noUnusedLocals`,死代码/未用导入直接报 TS6133;镜像构建时会 `npm run build` | -| 测试 | `pytest tests/ -q`(用 `douyu_login_test`);`ruff format` + `ruff check` |