Files
memind_adm/docs/DEPLOY.md
2026-06-30 20:26:33 +08:00

270 lines
11 KiB
Markdown
Raw Permalink 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_adm 部署与重启
> 2026-06-26 起,103 / Studio 正式禁止 `rsync` 发布。
> 唯一合法入口是 `bash scripts/release-prod.sh`。
>
> 本仓库是 **本机 Mac 开发仓库**。每次开发都必须形成 Git commit;本机不允许直接 `rsync` 到 `103` 或 `105`,只能从本地 commit 打包发布。
管理后台前端(React + Vite)部署到生产 Studio 服务器(SSH 优先 `john@10.10.0.2:22`,局域网不通时退回 `john@58.38.22.103:22`)。
## 环境概览
| 项 | 默认值 |
|---|---|
| 部署目标 | `john@10.10.0.2:/Users/john/Project/memind_adm`fallback `john@58.38.22.103` |
| 服务端口 | `5174` |
| 运行方式 | `vite preview`(静态资源 + API 反代) |
| 后端 API | 本仓库 `server/``ADM_API_PORT` 默认 `8085`,与 Memind portal 解耦) |
| 日志 | `/Users/john/Project/memind_adm/adm-preview.log` |
## 硬规则
`memind_adm` 允许项目独立,**不允许用户体系、权限体系、技能体系、策略体系独立**。
必须遵守:
1. 用户、登录会话、能力、策略、技能、账单都必须复用 `Memind` 主实现与主表。
2. `memind_adm` 不得再引入或恢复独立后台用户表,例如 `auth_users``auth_sessions` 这类本地表实现。
3. admin 账号必须是 `Memind` 主用户表中的同一账号,`npm run admin:init` 只允许更新主表账号密码,不允许新建旁路 admin 体系。
4. 生产环境必须显式指向 `Memind` 业务模块目录,不能依赖“碰巧命中”的相对路径。
5. 如果页面出现“用户、能力、技能、策略都是空的”,优先怀疑线上仍在跑旧代码,或 `MEMIND_LIB_ROOT` / 数据库连接未生效,不要先怀疑前端。
## 本次事故结论
2026-06-20 这次事故的根因不是生产库没数据,而是 **线上 `memind_adm` 实际仍在跑旧版独立鉴权代码**
1. 旧代码仍在查询 `auth_users`,没有切到 `Memind``createUserAuth()`
2. 远端 `.env` 虽然已经指向共享库和主库,但只改环境变量不等于新代码已生效。
3. `scripts/rsync_to_server.sh` 默认 **不会覆盖远端已有 `.env`**,所以改了本地环境模板后,线上配置不一定会自动更新。
结论:
1. “页面空”时,先查远端 `adm-api.log` 有没有 `auth_users`
2. 只看“部署脚本成功”不够,必须验远端实际代码和接口返回。
3. 涉及共享用户体系的改动后,必须做登录和 `/admin-api/users` 实测。
## 前置条件
1. 本机可 SSH 到 Studio 生产机:
```bash
ssh john@10.10.0.2
```
2. 本机已安装 Node.js,项目依赖已安装(`npm install`)。
3. Studio 服务器上 **memind_adm Admin API** 在 `8085` 运行(`remote_restart.sh` 会自动启动),MySQL 与 Memind 共用。
4. 103 服务器上必须存在可读的 `Memind` 业务目录,例如 `/Users/john/Project/Memind`。
5. 远端 `.env` 必须包含正确的共享环境变量:
`DATABASE_URL` 或 `MYSQL_*`
`MEMIND_LIB_ROOT=/Users/john/Project/Memind`
`H5_USERS_ROOT=/Users/john/Project/Memind/users`
## gadm 独立登录
`https://gadm.tkmind.cn` 应部署 **本仓库 memind_adm**,勿再反代到 `Memind/ops` Vite dev(旧版未登录会跳 `localhost:5173`)。
| 项 | 说明 |
|---|---|
| 登录 | 本页 `/auth/login`,账号来自共用 MySQL |
| 会话 | 设置 `H5_PUBLIC_BASE_URL=https://gadm.tkmind.cn`**不要**设 `H5_COOKIE_DOMAIN=.tkmind.cn` |
| 路径 | `https://gadm.tkmind.cn/` 直达超管后台;Plaza 运营在 `/ops``/ops/admin` 已废弃 |
| API | `ADM_DEV_BACKEND=http://127.0.0.1:8085`preview 反代目标) |
| 初始化 admin | `npm run admin:init` 只更新 `Memind` 主用户表中的 admin 密码,不创建独立后台账号 |
nginx 示例见 `scripts/gadm-nginx.conf.example``/ops/` → preview`/auth` `/admin-api` `/api` → Admin API `8085`)。
## 当前规则
1. 本地当前工作区先打成发布包,不直接覆盖 103。
2. 发布来源必须是可追溯的本地 commit,不允许从不明工作区直接上线。
3. 103 在切换前必须做 `memind_adm` 全量备份。
4. 发布包不能带 `.env`、日志、pid 文件、`.mindops/` 等运行态资产。
5. 103 必须先在 release 目录完成解包、`npm install`、`npm run build`,再切换 live 目录。
6. 切换后必须通过 Admin API 和前台首页健康检查;失败立即回滚。
## 唯一入口
```bash
bash scripts/release-prod.sh --dry-run
bash scripts/release-prod.sh
```
## 产物发布流程
1. 本地生成 `memind-adm-<release-id>.tar.gz` 和发布清单。
2. 通过 `scp` 上传到 103 的 `incoming/memind_adm/`。
3. 103 备份当前 `/Users/john/Project/memind_adm` 为时间戳压缩包。
4. 在 `/Users/john/Project/releases/` 下解包新版本。
5. 从当前 live 目录继承运行态配置与日志文件。
6. 在 release 目录安装依赖、构建。
7. 原子切换 `memind_adm` live 目录。
8. 调用 `scripts/remote_restart.sh` 重启 `8085` 和 `5174`。
9. 检查 `127.0.0.1:8085/health` 与 `127.0.0.1:5174/`。
## 禁止事项
- 禁止 `scripts/rsync_to_server.sh`
- 禁止手工拖文件覆盖 103
- 禁止在 103 直接改源码后继续跑
- 禁止跳过备份和健康检查
## 更新部署(历史)
下方 `rsync` 流程只保留作事故回溯背景。生产发布不要再照做。
旧流程示例:
```bash
./scripts/rsync_to_server.sh
```
脚本会依次:
1. 本地 `npm run build` 生成 `dist/`
2. `rsync` 同步源码到远端(排除 `node_modules`、`.git`、`.env` 等)
3. 单独同步 `dist/`
4. 若远端尚无 `.env`,写入默认配置(**不覆盖已有 `.env`**
5. 调用 `scripts/remote_restart.sh` 重启服务
注意:
1. 如果本次改动涉及 `DATABASE_URL`、`MYSQL_*`、`MEMIND_LIB_ROOT`、`H5_USERS_ROOT`,需要**手动同步远端 `.env`**`rsync_to_server.sh` 不会覆盖已有远端 `.env`。
2. 如果本次改动涉及共享用户体系,部署完成后必须执行下文“共享用户体系验收”。
3. 如果希望“套餐管理”自动同步到生产后台,还需要在远端 `.env` 配置 `PLAN_SYNC_TARGET_BASE_URL`、`PLAN_SYNC_USERNAME`、`PLAN_SYNC_PASSWORD`。
### 常用参数(历史)
```bash
# 跳过本地构建(沿用当前 dist/)
./scripts/rsync_to_server.sh --skip-build
# 只同步文件,不重启
./scripts/rsync_to_server.sh --no-restart
# 环境变量覆盖
DEPLOY_HOST=john@10.10.0.2 \
REMOTE_DIR=/Users/john/Project/memind_adm \
ADM_PORT=5174 \
./scripts/rsync_to_server.sh
```
## 仅重启服务
代码已在远端、无需重新同步时:
```bash
ssh john@10.10.0.2 'ADM_ROOT=/Users/john/Project/memind_adm ADM_PORT=5174 bash -s' \
< scripts/remote_restart.sh
```
或在 100 服务器上直接执行:
```bash
cd /Users/john/Project/memind_adm
ADM_PORT=5174 ./scripts/remote_restart.sh
```
重启逻辑:结束占用 `5174` 的进程 → `nohup npm run preview` → 检查首页是否返回 200。
## 验证
本机通过 SSH 检查:
```bash
ssh john@10.10.0.2 'curl -sI http://127.0.0.1:5174/ | head -1'
# 期望: HTTP/1.1 200 OK
```
查看远端日志:
```bash
ssh john@10.10.0.2 'tail -f /Users/john/Project/memind_adm/adm-preview.log'
```
## 远端配置
编辑远端 `.env`(首次部署后路径:`/Users/john/Project/memind_adm/.env`):
```env
# preview 反代目标(/auth、/admin-api、/api)— 指向本仓库 Admin API
ADM_API_PORT=8085
ADM_DEV_BACKEND=http://127.0.0.1:8085
H5_PUBLIC_BASE_URL=https://gadm.tkmind.cn
VITE_BASE_PATH=/ops
# 共享 Memind 主库与主实现
DATABASE_URL=mysql://<user>:<password>@<host>:3306/<db>
MEMIND_LIB_ROOT=/Users/john/Project/Memind
H5_USERS_ROOT=/Users/john/Project/Memind/users
# 套餐自动同步到生产后台(可选)
PLAN_SYNC_TARGET_BASE_URL=https://gadm.tkmind.cn
PLAN_SYNC_USERNAME=admin
PLAN_SYNC_PASSWORD=<admin-password>
PLAN_SYNC_TIMEOUT_MS=10000
# 「返回对话」跳转主 H5(可选)
VITE_MAIN_APP_URL=https://h5.tkmind.cn
```
修改 `.env` 后需重启服务生效。
## 共享用户体系验收
每次涉及用户/权限/技能/策略相关改动后,部署完成必须至少执行一次:
1. 看远端代码是否已切到共享实现:
```bash
ssh john@10.10.0.2 'cd /Users/john/Project/memind_adm && sed -n "1,80p" server/bootstrap.mjs'
```
期望:出现 `createUserAuth`,而不是 `createLocalUserAuth`。
2. 看远端 `server/local-auth.mjs` 是否只剩 cookie 工具:
```bash
ssh john@10.10.0.2 'cd /Users/john/Project/memind_adm && sed -n "1,80p" server/local-auth.mjs'
```
期望:**没有** `auth_users`、`auth_sessions`、`createLocalUserAuth`。
3. 看启动日志是否仍出现旧表查询:
```bash
ssh john@10.10.0.2 'cd /Users/john/Project/memind_adm && tail -n 120 adm-api.log'
```
期望:**没有** `auth_users`;出现 `Admin DB connected` 与 `Memind lib: /Users/john/Project/Memind`。
4. 实测登录和用户接口:
```bash
ssh john@10.10.0.2 'python3 - <<\"PY\"
import requests
s = requests.Session()
base = "http://127.0.0.1:8085"
print(s.post(base + "/auth/login", json={"username":"admin","password":"<admin-password>"}).status_code)
resp = s.get(base + "/admin-api/users", params={"page": 1, "pageSize": 5})
print(resp.status_code)
print(resp.text[:800])
PY'
```
期望:`/admin-api/users` 返回 200,且结果中能看到共享主表用户数据,不是空列表。
## 故障排查
| 现象 | 处理 |
|---|---|
| `无法 SSH 到 john@10.10.0.2` | 先确认局域网可达;不通时改走 `john@58.38.22.103`,必要时再执行 `ssh-copy-id john@58.38.22.103` |
| 首页 200 但登录失败 | 检查 Studio 上 `8085` Admin API 是否运行(`curl http://127.0.0.1:8085/health` |
| 用户、能力、技能、策略全空 | 先查 `adm-api.log` 是否仍有 `auth_users`;再核对远端 `server/bootstrap.mjs` 是否已切到 `createUserAuth()`;再核对远端 `.env` 的 `MEMIND_LIB_ROOT` 与 `DATABASE_URL` |
| 打开后跳 localhost:5173 | nginx 仍指向 Memind/ops dev;改反代到 memind_adm `:5174`,并重新部署 |
| `dist 不存在` | 先在本机 `npm run build`,或完整执行 `./scripts/rsync_to_server.sh` |
| 启动失败 | 查看 `adm-preview.log`;确认远端 Node 在 PATH 中(需 Homebrew `node@22` 等) |
| 端口被占用 | `remote_restart.sh` 会自动 kill 旧进程;仍异常时可手动 `lsof -iTCP:5174 -sTCP:LISTEN` |
## 相关脚本
| 脚本 | 说明 |
|---|---|
| `scripts/release-prod.sh` | 本地打发布包并推送到 103,再由 103 备份、解包、切换、重启 |
| `scripts/rsync_to_server.sh` | 已禁用,仅保留禁用提示 |
| `scripts/remote_restart.sh` | 仅在远端重启 `vite preview` |
| `scripts/.releaseignore-prod` | 生产发布包排除规则 |
## 规则文档
- `ENGINEERING_WORKFLOW_RULES.md`
- `DEVELOPMENT_RELEASE_RULES.md`
- `TEST_RELEASE_RULES.md`
- `PRODUCTION_RELEASE_RULES.md`