feat:cicd
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
---
|
||||
name: frontend-cicd-deploy
|
||||
overview: 参考 zt-closet-backend 的 Gitea Actions CI/CD,为前端管理后台编写 deploy 工作流:构建 dist 静态资源并通过 SSH 同步到生产机 nginx 目录 /www/zt-closet-manage.lzcwy.cn。
|
||||
todos:
|
||||
- id: create-deploy-workflow
|
||||
content: 新建 .gitea/workflows/deploy.yaml:checkout→setup-node→npm ci→npm run build→SSH+rsync 部署 dist 到 /www/zt-closet-manage.lzcwy.cn,含备份与回滚
|
||||
status: completed
|
||||
- id: verify-pipeline
|
||||
content: 校验工作流 YAML 语法与触发配置,确认凭据引用与后端一致
|
||||
status: completed
|
||||
dependencies:
|
||||
- create-deploy-workflow
|
||||
---
|
||||
|
||||
## 产品概述
|
||||
|
||||
为前端项目 `zt-closet-manage-frontend` 建立与后端一致的 CI/CD 流水线(Gitea Actions),实现「打标签自动构建 → 部署到生产机 nginx 静态目录」的全流程自动化。
|
||||
|
||||
## 核心功能
|
||||
|
||||
- 推送 `v*` 标签或手动触发(workflow_dispatch)时,自动安装依赖、类型检查并构建出 `dist` 静态产物。
|
||||
- 通过 SSH 将构建产物安全传输到生产机,部署到 nginx root 目录 `/www/zt-closet-manage.lzcwy.cn`。
|
||||
- 采用蓝绿目录原子切换部署,线上目录任何时刻都完整,失败秒级回滚,保证发布零中断。
|
||||
- 复用后端已有的 Gitea runner 与 SSH 部署凭据,无需重复配置密钥。
|
||||
|
||||
## 约束说明
|
||||
|
||||
- 前端为纯静态资源,不使用 Docker,构建产物直接放到 nginx 静态目录。
|
||||
- 前端 API baseURL 为 `/api/v1`,由生产 nginx 反代到 `127.0.0.1:8081`,构建无需改动 baseURL 与 vite 配置。
|
||||
- 产物结构(`index.html` + `/assets/` 带 hash 资源)与现有 nginx `try_files`、`/assets/` 长缓存配置匹配。
|
||||
|
||||
## 技术栈
|
||||
|
||||
- CI/CD:Gitea Actions(与后端 `zt-closet-backend` 一致),runner 环境 `ubuntu-latest`。
|
||||
- 构建:Node.js(匹配 `package.json` engines `^22.18.0 || >=24.12.0`,取 Node 22)+ npm。
|
||||
- 部署:SSH + rsync 传输到临时目录 + 蓝绿目录原子切换(mv)上线。
|
||||
|
||||
## 实现方案
|
||||
|
||||
参考后端 `.gitea/workflows/deploy.yaml` 的整体风格(name / on push tags `v*` + workflow_dispatch / concurrency / env / SSH heredoc 远端执行 / 健康检查与回滚),针对前端「纯静态资源」特点做如下调整:
|
||||
|
||||
- **去掉 Docker**:前端无需镜像构建,改为 `actions/checkout` → `actions/setup-node`(Node 22,启用 npm 缓存)→ `npm ci` → `npm run build`(内含 type-check + vite build)。
|
||||
- **产物传输用 rsync**:相比 scp,rsync 支持增量传输与 `--delete`,可清理临时目录中上一版本遗留的旧 hash 资源,传输更快、更干净。
|
||||
- **蓝绿目录原子切换(核心)**:新产物先 rsync 到临时目录 `/www/.zt-closet-deploy-tmp`(绝不动线上目录);校验临时目录 `index.html` 存在后,用 `mv` 原子切换:将当前线上目录改名为备份目录,再把临时目录改名为线上目录。任何一步失败,线上目录保持原样不受影响;切换后校验失败则把备份目录 `mv` 回去,秒级回滚。
|
||||
- **凭据复用**:直接沿用后端的 secret `ZT_CLOSET_PROD_SSH_KEY` 与 vars `ZT_CLOSET_PROD_SSH_HOST`、`ZT_CLOSET_PROD_SSH_USER`,生产机同一台,避免重复配置。
|
||||
|
||||
## 关键决策与权衡
|
||||
|
||||
- **蓝绿目录原子切换 而非 直接 rsync --delete 覆盖**:直接对线上目录 `--delete` 若传输中断,会出现「旧文件已删、新文件未传完」的半残状态导致站点 404;蓝绿方式线上目录始终完整,切换是一次 `mv`,零中断、回滚快。权衡是需 nginx 进程对 `/www` 目录有 rename 权限(root 运行 nginx 通常满足),且临时目录与线上目录需在同一分区才能 `mv`。
|
||||
- **rsync 而非 scp**:增量 + `--delete`(作用于临时目录)解决 Vite 带 hash 资源累积问题,传输量小、目录干净;需生产机预装 rsync(Linux 默认自带)。
|
||||
- **不改动 vite 配置**:默认 `base='/'` 与 nginx `root` 部署完全契合,`/assets/` 长缓存与 SPA `try_files` 均已就绪,零改动最安全。
|
||||
- **健康检查用文件校验**:静态站点无 `/ping` 接口,改用「线上目录 `index.html` 是否存在」作为成功判据,简单可靠。
|
||||
|
||||
## 实现要点
|
||||
|
||||
- **性能**:setup-node 开启 npm 缓存(`cache: true`),源码未变动时 `npm ci` 复用缓存,加快重建;rsync 增量避免全量传输。
|
||||
- **可靠性**:远端脚本 `set -e`,rsync 到临时目录 → 校验 index.html → `mv` 原子切换 → 切换后校验;失败则把备份目录 mv 还原,保证发布原子性与零中断;`concurrency.group: deploy` + `cancel-in-progress: false` 防止并发部署互相打断。
|
||||
- **安全**:SSH 私钥仅从 secret 注入,写入 `~/.ssh/deploy_key`(600 权限),`StrictHostKeyChecking=no` 仅用于自动化;不引入明文密钥;不改动业务代码与请求层。
|
||||
- **爆炸半径控制**:仅新增 `.gitea/workflows/deploy.yaml` 一个文件,不动现有源码、vite 配置与 nginx 配置;标签触发不影响日常 push。
|
||||
|
||||
## 架构设计
|
||||
|
||||
沿用后端现有分层部署链路,仅将「Docker 镜像」环节替换为「静态产物 rsync + 蓝绿切换」。
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
P[push tag v* / workflow_dispatch] --> CI[Gitea Actions Runner]
|
||||
CI --> B[setup-node + npm ci + npm run build]
|
||||
B --> D[dist 静态产物]
|
||||
D --> R[rsync over SSH 到临时目录]
|
||||
R --> V{校验 index.html}
|
||||
V -->|通过| M[mv 原子切换上线]
|
||||
V -->|失败| X1[保留线上旧版本]
|
||||
M --> N[生产机 /www/zt-closet-manage.lzcwy.cn]
|
||||
N --> X[nginx 对外提供 SPA + 反代 /api 到 127.0.0.1:8081]
|
||||
```
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
/root/zt-closet-manage-frontend/
|
||||
└── .gitea/
|
||||
└── workflows/
|
||||
└── deploy.yaml # [NEW] 前端构建部署流水线。触发:push tag v* 与 workflow_dispatch。步骤:checkout → setup-node(Node22, 开 npm 缓存) → npm ci → npm run build(type-check + vite build) → SSH 密钥 + rsync 将 dist/ 同步到临时目录 /www/.zt-closet-deploy-tmp → 校验 index.html 存在 → mv 蓝绿原子切换上线(线上目录改名为备份、临时目录改名为线上),切换后校验失败则 mv 备份还原。复用后端 secret ZT_CLOSET_PROD_SSH_KEY 与 vars ZT_CLOSET_PROD_SSH_HOST/ZT_CLOSET_PROD_SSH_USER。
|
||||
```
|
||||
Reference in New Issue
Block a user