Files
fangke/docs/superpowers/specs/2026-09-29-git-and-deploy-automation-design.md
T

100 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Git 托管接入 + 一键部署方案 — 设计文档
日期:2026-09-29
分支:m1
状态:设计已获用户批准
远程仓:http://219.157.255.213:25311/xinyouhe/fangke.git(用户自建)
## 背景与目标
当前部署是"约定驱动的手工链":流程存在于对话上下文与一条记忆中,每次由 AI 手工执行 6-8 步(构建→scp 经跳板→解压→cp 到正确挂载点→docker 重建→探活→哈希核对)。已两次踩中"解压到错误目录"同类坑(/opt/cms-cj/dist 而非 admin/dist)。仓库无 git remote,无任何部署脚本。
目标:
1. 项目托管到用户提供的自建 git 远程仓(版本化/备份)。
2. 部署固化为仓库内一键脚本 `deploy/deploy.sh`——用户说"部署到线上"时 AI 执行该命令;日常任务完成后的标准部署走同一条命令。
3. 消灭手工多步流程的错误类(错误目录/静默半部署/漏验证)。
## Part 1:Git 远程仓初始化
1. `git remote add origin http://219.157.255.213:25311/xinyouhe/fangke.git`
2. **推送前卫生处理**(实现时以当时 `git status` 实测为准,按以下原则逐文件决策):
- 被代码引用的资产(如 LoginLeftView 引用的图片)→ 提交入库
- 设计文档/设计稿(assets/design 等)→ 提交入库(团队知识)
- 临时验证产物(根目录截图、测试页 html、.playwright-mcp/、.tmp-*)→ .gitignore
- **.gitignore 必须在本期初始提交中即包含 `deploy/logs/`**——否则首次部署产生的日志污染工作区,下一次部署被自身的"工作区干净"前置门禁拦住
- 敏感文件扫描:确认无 .env/私钥/明文密码入库(.env.example 除外);deploy/.env 不存在于本机(仅服务器有)
- 首次 push 到 http 远程会弹凭证(Windows Git Credential Manager 交互一次后缓存)——一次性用户侧操作,AI 执行 push 前需用户确认凭证已配好
3. 推送 `m1` 与 `main` 两分支(m1 为当前功能分支)。
4. 后续提交按既有节奏正常 push(不做 push 即部署——见"明确不做")。
## Part 2:deploy/deploy.sh 一键部署脚本
### 用法
```
bash deploy/deploy.sh <server|admin|sdk|all> [--skip-tests] [--allow-dirty]
```
- 单目标只走对应子集(如仅改 admin 时 30 秒级完成)
- `all` 按依赖序执行:**server → admin → sdk**(SDK 新事件依赖 server 白名单先上线)
### 脚本顶部配置(环境变量可覆盖)
```
JUMP_HOST=root@8.152.213.143 # 跳板
TARGET=root@47.254.176.10 # 生产服务器
SSH_KEY=~/.ssh/id_ed25519
REMOTE_DIR=/opt/cms-cj
SITE_URL=https://tracker.12418113.xyz
```
### all 完整流程(固化现手工链 + 全部已知陷阱防御)
| 步骤 | 内容 | 防的坑 |
|---|---|---|
| 1 前置 | git 工作区干净(`--allow-dirty` 逃生舱);跳板 SSH 可达 | 部署未提交状态 |
| 2 测试门禁 | server: pytest tracker/tests(188 基线);sdk: vitest run + tsc;admin: vue-tsc(build 内含) | 带病上线 |
| 3 构建 | admin: `NODE_OPTIONS=--max-old-space-size=6144 pnpm build`;sdk: build + gzip 字节数记录 | 本机 OOM |
| 4 打包与传输 | **tar 按真实路径打包**(非暂存 dist/ 方案):admin/sdk 目标打 `admin/dist sdk/dist`;server 目标打 `server/`(排除 __pycache__/db.sqlite3/.pytest_cache;**绝不打包 node_modules/.git/docs**)→ scp 经跳板 → /tmp | 根目录 tar 连 node_modules 一起传 |
| 5 服务器侧 | 在 $REMOTE_DIR 解压——**tar 真实路径直接落位挂载点**(admin/dist、sdk/dist 原地合并覆盖,无 cp、无暂存、无清理步骤——彻底消灭"解压到错误目录"路径);server: `docker compose up -d --build web`(Dockerfile 内自动 migrate) | 错误挂载点目录(×2 历史) |
| 6 验证 | tracker-web 容器 Up;`curl -f $SITE_URL` → 200;admin:`sha256(curl $SITE_URL 的 index.html) === sha256(本机 admin/dist/index.html)`;sdk:`curl $SITE_URL/sdk/v1.js` 含新 build_id | 部署无效/缓存误判 |
| 7 记录 | deploy/logs/deploy-<时间戳>.log:git 哈希/部署目标/版本标识/验证结果/耗时(logs 目录 gitignore,已在 Part 1 落地) | 无部署历史可追溯 |
### 单目标语义(每个目标都完整走:前置检查 + 自己的测试 + 自己的验证)
| 目标 | 子集 |
|---|---|
| server | pytest → tar server/ → 解压 $REMOTE_DIR → docker compose up -d --build web → 容器 Up + `curl -f $SITE_URL` 200(无 dist 传输) |
| admin | vue-tsc/build → tar admin/dist → 解压落位 → index.html sha256 线上比对(无 docker、无 pytest) |
| sdk | vitest + tsc → build → tar sdk/dist → 解压落位 → 线上 v1.js 含 build_id(无 docker) |
### 失败语义
`set -euo pipefail`;任一步失败立即中止并输出失败步骤与原因——**杜绝静默半部署**。单目标失败时 `all` 序列停止(不做部分继续)。
### 平台约束
- 脚本为 bash(开发机 Git Bash 执行;服务器侧命令经 ssh 执行,无 Windows 依赖)
- 服务器现有 1Panel/OpenResty 等其他项目**严格不触碰**(既有红线)
## Part 3:使用约定(新建 CLAUDE.md + 更新会话背景与记忆)
现状核实:仓库与用户级**均无 CLAUDE.md**——部署约定目前活在用户每会话粘贴的"项目背景"块与 AI 自动记忆中。落地:
1. **新建仓库 CLAUDE.md**(部署约定段):用户说"部署到线上" → AI 执行 `bash deploy/deploy.sh all`(或按改动范围选单目标)并汇报验证结果与版本标识;任务完成后的标准部署 = 同一条命令;部署日志位于 deploy/logs/。
2. **用户侧**:其后会话粘贴的"项目背景"块中"部署策略"段改为指向本脚本(由用户自行更新其模板,spec 不代写)。
3. **AI 自动记忆**:更新既有"前端部署目标目录"记忆条目——手工链描述作废,指向 deploy/deploy.sh(历史陷阱教训保留)。
## 明确不做(本期)
- push 触发自动部署(webhook/CI):git 服务器无暴露接收端口必要;未来升级时 CI 可直接调用本脚本(接口即命令行)
- 服务器侧构建:构建留在开发机,服务器保持纯 Docker 运行态
- 自动回滚机制:出问题走"再改再发"(单管理员低频部署,YAGNI;部署日志保留上一版哈希可供人工对照)
## 验证计划
1. 脚本干跑:单目标 admin 部署一次(近期 admin 已是最新,重部署无损)验证全流程
2. `all` 全量部署一次(当前三端均为最新代码,等价幂等重部署)验证顺序与哈希核对
3. 故意注入失败(如断开跳板模拟)验证"失败即停"语义
4. git push 后远程仓确认两分支与提交历史完整