Files
memind/docs/release-deploy.md
T
john 70492d9eba Add attachment text extraction, auto web news skill, and chat/voice UI updates.
Simplify asset upload temp paths, refresh deploy docs for Aliyun DNS topology, and ship MindSpace content-scan and auth improvements.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-20 15:08:10 +08:00

298 lines
10 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.
# Memind 生产更新发布指南
> 本文描述如何把本地开发代码安全发布到 **g2.tkmind.cn** 生产环境。
> 发布前请先阅读 [生产 / 测试 / 预览隔离规程](./service-isolation-runbook.md),避免误占生产端口或覆盖用户数据。
## 1. 架构与发布目标
用户访问 `https://g2.tkmind.cn/` 的流量路径:
```text
阿里云解析(DNS
→ 105 服务器(公网入口 / 反代)
→ 本地 Mac 1.6 机器(主服务)
├─ 主流量 → 本地 Portal127.0.0.1:8081
└─ 备用/灰度 → 105 Portal(经隧道 127.0.0.1:18080 → :8080
```
两台 Portal 都是 **无状态前端**,共用 Studio 上的 goosed 与 MindSpace 数据目录。
| 角色 | 机器 | 代码目录 | 服务 | 重启方式 |
|------|------|----------|------|----------|
| 生产主 | 本地 Mac 1.6 机器 | `/Users/john/Project/Memind` | Portal `:8081`、Plaza `:3001` | `launchctl kickstart` |
| 入口转发 | 105 服务器 | 入口转发配置 | 反代 `:80/:443` | 阿里云解析切换后生效 |
| 灰度副 | 105(经 Tailscale `ssh105` | `/root/tkmind_go/ui/h5` | `goose-h5` `:8080` | `systemctl restart goose-h5` |
更详细的流量与灰度比例说明见 [g2 负载均衡](./g2-load-balancing.md)。
## 2. 目录与环境对照
| 环境 | 典型目录 | 端口 | 用途 |
|------|----------|------|------|
| **生产(Studio** | `/Users/john/Project/Memind` | `8081` / `3001` | 线上 g2 / plaza |
| **开发预览** | `/Users/john/Project/test/Memind` 或本机副本 | `18081` / `13001` | 本地联调,禁止占 `8081` |
| **105 副机** | `/root/tkmind_go/ui/h5` | `8080` | g2 灰度流量 |
**重要:** `rsync_to_server.sh` 会把**你执行命令时所在的本地目录**同步到 Studio 生产目录。发布前请确认当前目录里的代码就是你要上线的版本,而不是半成品或未验证的分支。
## 3. 发布入口(主流程)
**推荐唯一入口:** 项目根目录的 `rsync_to_server.sh`
```bash
cd /path/to/your/memind-repo # 开发完成、已自测的目录
# ① 预览(不修改任何远端)
./rsync_to_server.sh --dry-run
# ② 正式发布(Studio + 105 全量)
./rsync_to_server.sh
```
脚本会自动完成:
1. 本地 Pre-flight(关键文件、安全 patch、exclude 规则)
2. Studio Pre-flightSSH、`.env`、MindSpace、data 完整性)
3. 交互确认(可用 `--yes` 跳过)
4. rsync 代码 → Studio 生产目录
5. rsync 后校验(`.env` 未变、MindSpace 未减少、patch 仍在)
6. Studio 上 `npm install` + `npm run build`
7. 重启本地 Mac 1.6 Portal → Plaza,并做健康检查
8. 经 Studio 触发 `scripts/sync-to-105.sh`,同步并重启 105
## 4. 发布前检查清单
`./rsync_to_server.sh` 之前,逐项确认:
### 4.1 本地构建与测试
```bash
pnpm install # 依赖有变更时
pnpm run build # 前端改动必须能编过
pnpm test # 建议跑;涉及核心逻辑时必跑
```
| 改动类型 | 是否必须 build | 能否 `--skip-build` |
|----------|----------------|---------------------|
| 前端(`.tsx` / `.css` / `src/` | **是** | 否 |
| 仅后端(`.mjs`) | 否(但 build 无害) | 可以 |
| 仅文档 / 脚本 | 否 | 可以 |
### 4.2 生产在线(只读)
```bash
curl -s http://127.0.0.1:8081/api/status # 本地 Portal,期望 ok
curl -s http://127.0.0.1:18080/api/status # 105 隧道,期望 ok
```
105 联通必须走 Tailscale,不要用公网 IP
```bash
ssh ssh105 'echo tunnel-ok-105'
```
### 4.3 安全约束(脚本会自动检查)
- `server.mjs` 必须含 `WORKSPACE_MAINTENANCE_ENABLED` patch(否则 105 重启会在 rclone 挂载上卡死)
- `.env``MindSpace/``data/` 在 exclude 列表中,**不会被 rsync 覆盖**
- rsync 使用 `--delete`:本地已删的文件会从 Studio 删掉(exclude 外的路径)
### 4.4 发布范围确认
- `rsync_to_server.sh` 同步的是**整个仓库**(除 exclude 外),不是单个文件
- 工作区若有未完成的其它改动,会一并上线——发布前建议 commit 或整理干净
- 涉及数据库迁移、批量清数据、支付回调测试等,**不要**直接在生产目录试跑,见 [隔离规程](./service-isolation-runbook.md)
## 5. 分步与保守发布
`rsync_to_server.sh` 支持的常用参数:
| 参数 | 作用 | 适用场景 |
|------|------|----------|
| `--dry-run` | 只预览 diff,不改远端 | **每次正式发布前必做** |
| `--only-100` | 只更新本地主机,不推 105 | 先让主流量生效,105 稍后 |
| `--only-105` | 只触发本地主机→105 同步 | 主机已是最新,只补 105 |
| `--skip-build` | 跳过远端 `npm run build` | 纯后端改动且确认 dist 无需更新 |
| `--no-restart` | 只同步代码,不重启服务 | 分批发布;需自行重启 |
| `--yes` / `-y` | 跳过交互确认 | 自动化或你已看过 dry-run |
示例:
```bash
# 只发 Studio(主流量 95%
./rsync_to_server.sh --only-100
# 纯 server.mjs 改动,跳过 build
./rsync_to_server.sh --skip-build
# 先同步代码,稍后再重启
./rsync_to_server.sh --no-restart
# 之后在 Studio 上手动 kickstart,或再跑一遍带重启的同步
```
## 6. 105 单独同步
若 Studio 代码已是最新,只需更新 105:
```bash
# 在 Studio 生产目录执行
cd /Users/john/Project/Memind
bash scripts/sync-to-105.sh
# 或从本地只触发 105 链路
./rsync_to_server.sh --only-105
```
`sync-to-105.sh` 会:
1. rsync 代码(`--delete`)与 `dist/``root@ssh105:/root/tkmind_go/ui/h5`
2. 远端 `npm install` + `npm run build`(可用 `SKIP_BUILD=1` 跳过)
3. `systemctl restart goose-h5`
4. 校验关键文件 md5 与 `:8080/api/status`
环境变量(可选):
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `H5_DEPLOY_HOST` | `root@ssh105` | 105 SSH 目标 |
| `H5_REMOTE_DIR` | `/root/tkmind_go/ui/h5` | 105 代码路径 |
| `H5_SYSTEMD_SERVICE` | `goose-h5` | systemd 服务名 |
| `SKIP_BUILD` | `0` | `1` 跳过远端 build |
| `NO_RESTART` | `0` | `1` 不重启服务 |
package.json 中的 `pnpm deploy:105` 等价于本地执行 `bash scripts/sync-to-105.sh`(需本机能 SSH 到 105,或已在 Studio 上)。
## 7. 发布过程与影响窗口
全量 `./rsync_to_server.sh` 典型耗时 **510 分钟**
| 阶段 | 用户可见影响 |
|------|----------------|
| rsync + npm install + build | 无(旧进程仍在跑) |
| 本地 Portal 重启 | **8081 短暂不可用**,约 10~40 秒;主流量可能短暂 502 |
| 105 goose-h5 重启 | **灰度流量(约 5%** 短暂不可用 |
| Plaza 重启 | plaza.tkmind.cn 可能短暂不可用;与 g2 主聊天无关 |
入口反代会对不健康上游做健康检查,105 重启期间可能暂时从池中摘除。
## 8. 发布后验证
### 8.1 健康检查
```bash
curl -s http://127.0.0.1:8081/api/status
curl -s http://127.0.0.1:18080/api/status
curl -s https://g2.tkmind.cn/api/status
```
### 8.2 确认命中哪台上游
g2 响应头 `X-Memind-Upstream`
- `127.0.0.1:8081` → 本地 Mac 1.6 机器
- `127.0.0.1:18080` → 105
```bash
curl -s -D - -o /dev/null https://g2.tkmind.cn/api/status | grep -i x-memind-upstream
```
### 8.3 业务冒烟
按本次改动选手动验证,例如:
- 打开 g2 聊天页,测试新功能
- 登录 / 微信 OAuth(若动到 auth
- MindSpace 页面读写(若动到 pages
- Plaza 列表(若动到 plaza
### 8.4 日志
```bash
# 本地 Portal
tail -f ~/Library/Logs/memind-portal.log
# Studio Plaza
tail -f ~/Library/Logs/plaza-prod.log
# 105(经 ssh105
ssh ssh105 'journalctl -u goose-h5 -n 50 --no-pager'
```
## 9. 回滚思路
项目没有一键回滚脚本,常见做法:
1. **代码回滚:** 在本地 git 回到上一个 good commit`./rsync_to_server.sh` 再发一版
2. **仅本地主机:** 若 105 有问题,可临时把流量全部收回主机(见 [g2-load-balancing.md](./g2-load-balancing.md)
3. **紧急恢复 Portal** 若 8081 挂了,见 [隔离规程 · 事故恢复](./service-isolation-runbook.md#事故恢复最小步骤)
发布前建议打 tag 或记录当前 commit,便于回滚:
```bash
git rev-parse HEAD
git tag -a release-2026-06-19 -m "before voice UI deploy"
```
## 10. 其它发布路径(非 g2 主站)
### 10.1 同步到局域网测试机
仅源码同步到 `192.168.1.9` 上的 test 目录,**不是生产**:
```bash
bash scripts/deploy-to-test-host.sh --dry-run
bash scripts/deploy-to-test-host.sh
```
目标:`test-memind` / `test-memindadm` / `test-memindplaza`。同步后需按该机习惯手动重启服务。
### 10.2 Plaza 105 静态站
```bash
pnpm deploy:plaza-105
```
依赖 goose-h5 已部署(`pnpm deploy:105` 或全量 rsync)。详见 [Plaza 本机部署](./plaza-local.md)。
### 10.3 已废弃 / 不可用
| 命令 | 状态 |
|------|------|
| `pnpm deploy:prod` | 指向 `../../deploy/deploy-h5-prod.sh`,当前仓库旁路不存在,**勿用** |
## 11. 推荐发布 SOP(标准作业)
适合大多数功能迭代的固定步骤:
```text
1. 在测试端口完成开发与自测(18081,勿占 8081)
2. pnpm run build && pnpm test
3. ./rsync_to_server.sh --dry-run ← 看清将要同步什么
4. 确认无多余改动、无数据库破坏性操作
5. ./rsync_to_server.sh ← 全量 Studio + 105
6. curl 健康检查 + 浏览器冒烟
7. 观察 5~10 分钟日志,确认无 ERROR 尖峰
```
**保守版(先主后副):**
```text
14 同上
5. ./rsync_to_server.sh --only-100
6. 冒烟通过后
7. ./rsync_to_server.sh --only-105
```
## 12. 相关文档
| 文档 | 内容 |
|------|------|
| [service-isolation-runbook.md](./service-isolation-runbook.md) | 生产 / 测试端口隔离、禁止事项、事故恢复 |
| [g2-load-balancing.md](./g2-load-balancing.md) | g2 权重、105 隧道、灰度比例调整 |
| [local-dev.md](./local-dev.md) | 本地开发端口与 preview |
| [plaza-local.md](./plaza-local.md) | Plaza 部署与 Tunnel |
---
**维护说明:** 若部署脚本路径、主机名或 systemd 服务名变更,请同步更新本文与 `rsync_to_server.sh` 头部注释。