Files
proxy-station/.claude/skills/deploy/SKILL.md
YANG JIANKUAN 5326c572a2 feat: 合并边缘节点运维并完善 Surge 配置安全
迁入通用节点部署工具、离线交付页生成器和共用技能,隔离真实配置与交付产物。统一 Codex 与 Claude Code 开发约定,补充节点迁移与运维文档。

完善 FINAL、策略组引用、输入校验、Surge 字段编码与 AI DNS 例外保护,增加隔离测试和订阅验证工具。

验证:全量类型检查、44 项单测、前端构建、脚本语法、技能入口与凭据隔离检查均通过。
2026-10-03 23:19:59 +08:00

62 lines
5.3 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.

---
name: deploy
description: 将 proxy-station 前端、后端或两者部署到 LA 生产服务器。用于用户要求部署、发布、上线、更新线上或同步到 la;生产数据维护使用 update-db。
---
# 部署 proxy-station 到 LA
线上是一台 1 核 1.9G 的机器,没有 Docker:后端用 Node 22 直跑、systemd 守护(服务名 `proxy-station`,代码在 `/opt/proxy-station`),前端在本机构建后由后端静态托管,HTTPS 与反代由 aaPanel 的 nginx 负责。首次部署与一次性配置(systemd 单元、`/etc/proxy-station/env`、nginx 站点、证书、数据库迁移)见 `docs/DEPLOY.md`,本 Skill 只负责日常的代码更新。
本技能由 Codex 与 Claude Code 共用,命令在仓库根目录运行;`.agents/skills/deploy` 链接到本目录。阅读或加载技能不代表用户授权上线;用户已明确要求本次部署时直接按授权执行,不重复确认。
## 用法
```bash
bash .claude/skills/deploy/scripts/deploy.sh all # 前后端一起(默认)
bash .claude/skills/deploy/scripts/deploy.sh web # 只换前端产物,不重启服务
bash .claude/skills/deploy/scripts/deploy.sh server # 只推后端源码,装依赖并重启服务
```
可选开关:
| 开关 | 作用 | 什么时候用 |
|---|---|---|
| `--skip-checks` | 跳过本地 typecheck 与单测 | 本轮已经跑过且代码没再改 |
| `--skip-build` | 不重新构建前端,直接推现有 `web/dist` | 刚构建过,只是重推 |
| `--host <别名>` | 换目标机器(默认 `la`) | 以后有第二台时 |
也可用环境变量覆盖 `DEPLOY_REMOTE_DIR`、`DEPLOY_SERVICE`、`DEPLOY_PUBLIC_URL`、`DEPLOY_RUN_USER`。
## 怎么选目标
- 改动只在 `web/` 下(页面、样式、前端逻辑)→ `web`。前端产物是静态文件,后端按请求读盘,换完立刻生效,不打断已连接的客户端拉订阅。
- 改动在 `server/` 或 `shared/` → `server`。`shared/` 是前后端共用源码,动了它通常前端也要重建,这时用 `all` 更稳。
- 拿不准就用 `all`,多花的只是一次前端构建的几秒钟。
## 脚本做了什么,以及为什么
1. **预检**:拒绝大写 ssh 别名(大写会被当作域名走 fake-IP 解析,连不上);确认远端目录与 systemd 单元存在,否则提示先做首次部署。
2. **本地检查**:后端目标先跑 typecheck 与单测。线上没有测试环境,这是最后一道拦截。
节点/组/规则/DNS/生成器变更另按 [Surge 变更验证](../../../docs/SURGE-CHANGES.md) 验证候选订阅,使用本机官方 `surge-cli`,涉及规则集时通过 `scripts/check-surge.py --fetch-rulesets` 下载快照验证。单测中本地 Surge CLI 用例在未安装时会跳过,不能据此声称已通过官方校验。
3. **推送**:用 tar 管道走 ssh,不依赖远端 rsync。先解到暂存目录再整体换入,旧版本保留为 `*.old`,中途失败不会留下半新半旧的目录。
4. **后端**:`pnpm install --frozen-lockfile --prod` 只装 server 及其 workspace 依赖,然后重启服务,等 `/api/health` 最多 20 秒。不通过就打印日志、把源码换回 `.old` 并重启,让线上先恢复。
5. **校验**:不用「命令没报错」当成功。前端比对本地与远端 `web/dist` 的文件树指纹,并检查公网首页是否已引用新的入口脚本;后端比对 `server/src` 与 `shared/src` 的指纹并确认服务 active;最后从本机访问公网健康检查,并确认管理接口不带 token 时返回 401。任何一项不过,脚本以失败退出。
脚本运行时会主动剥掉会话注入的 HTTP 代理环境变量,ssh/pnpm/curl 都直连。
## 结果怎么读
- 最后一行 `部署完成:<目标> @ <git rev>` 才算成功。把这一行连同校验段落转述给用户。
- 输出里出现 `(工作区有未提交改动)` 时要提醒用户:线上跑的是未提交的代码,之后应当提交或有意识地保持。
- 生成器或 shared 变更部署后,从实际 HTTPS 入口取订阅,用 `python3 scripts/check-surge.py <私有临时文件> --fetch-rulesets` 再验收;健康检查和源码指纹不能证明规则行为正确。受影响的 Clash 用独立目录下的 `mihomo -t` 验证。
- `前端产物指纹不一致` 几乎只有一种原因:推送中断。重跑一次 `web` 即可。
- `公网首页未引用 <入口脚本>` 而指纹一致:浏览器或中间缓存,稍等再试;aaPanel 的反代模板对 js 只缓存 1 分钟。
- `pnpm install 失败`:多半是本地 `package.json` 改了但锁文件没更新。本地 `pnpm install` 后连锁文件一起提交,再部署。
- 健康检查失败并回滚:回滚只恢复源码,不恢复依赖。到本地用 `pnpm --filter @proxy-station/server start` 复现,别在线上反复重启。
## 边界
- 数据库迁移、`ADMIN_TOKEN`、nginx 与证书属于另行授权的首次配置或维护任务,见 `docs/DEPLOY.md`;本次代码部署授权不包含这些操作。已有明确授权时不重复确认。
- 不做 git 提交。部署与提交是两件事,用户没要求就不要顺手提交。
- 如果用户要部署到 LA 之外的机器,先确认那台机器已按 `docs/DEPLOY.md` 完成首次部署,再用 `--host` 与环境变量指向它。