feat(ci): P1-4 前端预览环境实施(轻量版) #482

Merged
auto-approve-bot merged 4 commits from ci/p1-4-preview-environment into develop 2026-07-17 19:43:42 +08:00
Owner

功能概述

实现 PR 级前端预览环境(轻量版),每个前端 PR 自动部署一个独立预览站。

变更内容

新增文件

  1. .gitea/workflows/preview-deploy.yml - 预览部署工作流

    • 触发条件:PR 打开/更新/重新打开时
    • 功能:自动构建前端 → 通过 rsync 部署到预览目录 → PR 评论贴预览链接
    • 预览 URL 格式:https://pr-{号}.preview.xiaoxiajianji.com
    • 使用 VITE_API_URL=https://staging-api.xiaoxiajianji.com 构建
  2. .gitea/workflows/preview-cleanup.yml - 预览清理工作流

    • 触发条件:PR 关闭/合并时
    • 功能:自动删除服务器上对应的预览目录
  3. scripts/ci/preview_init_server.sh - 服务器初始化脚本

    • 创建 /var/www/preview/ 目录
    • 生成测试页面
    • 输出 Nginx 配置建议
  4. scripts/ci/preview_nginx.conf.template - Nginx 配置模板

    • 通配符 server_name:*.preview.xiaoxiajianji.com
    • 动态路由:根据子域名映射到 /var/www/preview/pr-{N}/
    • API 反向代理:/api/*staging-api.xiaoxiajianji.com
    • SPA 路由支持:try_files $uri /index.html

技术方案

  • 静态文件方案:不用 Docker,直接部署静态文件到 Nginx 目录
  • 部署方式:rsync 通过 SSH 上传到业务服务器
  • API 代理:Nginx 反向代理到 staging API
  • Runner:使用 runtime-builder(有 npm 缓存和 SSH 密钥)

服务器端配置(需手动执行一次)

# 1. 运行初始化脚本
bash scripts/ci/preview_init_server.sh

# 2. 配置 Nginx
# 将 scripts/ci/preview_nginx.conf.template 复制到 Nginx 配置目录

# 3. 配置 DNS
# *.preview.xiaoxiajianji.com → 47.98.113.167

# 4. 配置 SSL(可选,先用 HTTP 也行)
# 推荐使用 Let's Encrypt 通配符证书

后续优化方向

  • 配置 SSL 证书(HTTPS)
  • 增加前端变更检测(无前端变更时跳过构建)
  • 预览环境过期自动清理
  • 预览环境健康检查
## 功能概述 实现 PR 级前端预览环境(轻量版),每个前端 PR 自动部署一个独立预览站。 ## 变更内容 ### 新增文件 1. **`.gitea/workflows/preview-deploy.yml`** - 预览部署工作流 - 触发条件:PR 打开/更新/重新打开时 - 功能:自动构建前端 → 通过 rsync 部署到预览目录 → PR 评论贴预览链接 - 预览 URL 格式:`https://pr-{号}.preview.xiaoxiajianji.com` - 使用 `VITE_API_URL=https://staging-api.xiaoxiajianji.com` 构建 2. **`.gitea/workflows/preview-cleanup.yml`** - 预览清理工作流 - 触发条件:PR 关闭/合并时 - 功能:自动删除服务器上对应的预览目录 3. **`scripts/ci/preview_init_server.sh`** - 服务器初始化脚本 - 创建 `/var/www/preview/` 目录 - 生成测试页面 - 输出 Nginx 配置建议 4. **`scripts/ci/preview_nginx.conf.template`** - Nginx 配置模板 - 通配符 server_name:`*.preview.xiaoxiajianji.com` - 动态路由:根据子域名映射到 `/var/www/preview/pr-{N}/` - API 反向代理:`/api/*` → `staging-api.xiaoxiajianji.com` - SPA 路由支持:`try_files $uri /index.html` ## 技术方案 - **静态文件方案**:不用 Docker,直接部署静态文件到 Nginx 目录 - **部署方式**:rsync 通过 SSH 上传到业务服务器 - **API 代理**:Nginx 反向代理到 staging API - **Runner**:使用 `runtime-builder`(有 npm 缓存和 SSH 密钥) ## 服务器端配置(需手动执行一次) ```bash # 1. 运行初始化脚本 bash scripts/ci/preview_init_server.sh # 2. 配置 Nginx # 将 scripts/ci/preview_nginx.conf.template 复制到 Nginx 配置目录 # 3. 配置 DNS # *.preview.xiaoxiajianji.com → 47.98.113.167 # 4. 配置 SSL(可选,先用 HTTP 也行) # 推荐使用 Let's Encrypt 通配符证书 ``` ## 后续优化方向 - [ ] 配置 SSL 证书(HTTPS) - [ ] 增加前端变更检测(无前端变更时跳过构建) - [ ] 预览环境过期自动清理 - [ ] 预览环境健康检查
xiaoxia added 4 commits 2026-07-17 19:15:17 +08:00
feat(ci): add preview nginx configuration template
Auto Merge CI PRs / Auto Merge on CI Green + Approved (pull_request) Failing after 1s
CI Build & Deploy Pipeline / Build Staging API Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Production Web Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Production API Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI Build & Deploy Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI Build & Deploy Pipeline / Deploy Production (pull_request) Has been skipped
CI Build & Deploy Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 12s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 1m5s
AI Code Review / AI Code Review (pull_request) Successful in 2m17s
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Successful in 2m34s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m36s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 4m22s
Auto Approve CI PRs / Auto Approve on CI Green (pull_request) Successful in 4m41s
5a91e3679a
Collaborator

代码审查结果 - PR #482

⚠️ 问题(3个需要修改)

  1. .gitea/workflows/preview-deploy.yml 第36-46行:存在 Tar 路径穿越安全风险

    • 问题描述:在 Python 脚本中解压 tarball 时,代码手动修改了 member.name 以去除 root_prefix,但未对修改后的路径进行校验。如果恶意构建的 tar 包中包含文件名如 ../../etc/passwd,在去除前缀后可能保留路径穿越字符,导致文件被解压到工作目录之外。
    • 修改建议:在 tar.extract 之前,必须检查 member.name 是否包含 .. 或是否以 / 开头(绝对路径)。建议使用 if ".." in member.name or member.name.startswith("/"): continue 或抛出异常。
  2. .gitea/workflows/preview-deploy.yml 第181行 & .gitea/workflows/preview-cleanup.yml 第62行:SSH 连接存在中间人攻击风险

    • 问题描述:在使用 ssh 连接时显式使用了 -o StrictHostKeyChecking=no。虽然之前执行了 ssh-keyscan,但关闭严格主机密钥检查会使连接容易受到中间人攻击,且使得 known_hosts 机制失效。
    • 修改建议:移除 -o StrictHostKeyChecking=no,依赖 ssh-keyscan 写入的 known_hosts 文件进行验证。如果担心首次连接问题,应确保 ssh-keyscan 成功且指纹正确。
  3. .gitea/workflows/preview-deploy.yml 第168行 & .gitea/workflows/preview-cleanup.yml 第48行:硬编码敏感的基础设施信息

    • 问题描述:代码中硬编码了默认的 STAGING 服务器 IP 地址 47.98.113.167。将真实的公网 IP 地址提交到代码仓库中会暴露基础设施信息,增加被攻击的风险,且不利于后续基础设施的迁移或变更。
    • 修改建议:移除默认值,如果 Secret 缺失则直接报错退出,避免使用硬编码的回退值。

💡 建议(2个可选)

  1. .gitea/workflows/preview-deploy.yml 第242行:评论查找逻辑较为脆弱

    • 建议描述:查找已有评论的逻辑依赖于字符串 '预览环境已部署' 存在且 'Preview URL' 不存在。这种基于特定文本内容的匹配方式非常脆弱,一旦评论文案发生微调(如翻译、格式调整),就会导致无法更新评论而重复发布。建议在评论中插入一个隐藏的 HTML 标记(如 <!-- preview-comment-marker -->)来唯一标识该评论。
  2. scripts/ci/preview_nginx.conf.template 第1行:HTTPS 配置与 Workflow 输出不一致

    • 建议描述:Nginx 配置模板中仅启用了 HTTP (80端口) 监听,HTTPS (443端口) 配置块被注释。但在 Workflow 中向用户输出的预览链接是 https://...。如果服务器未配置 SSL 或默认重定向,用户访问链接会失败。建议确认环境是否已配置 HTTPS,若未配置,Workflow 输出链接应改为 http,或者完善 Nginx 模板以支持 HTTPS。

格式检查通过 | 逻辑审查需修改 | ⚠️ 建议关注性能


🤖 由 AI 代码审查机器人自动生成 | 2026-07-17 19:17:35 | 模型:

## 代码审查结果 - PR #482 ### ⚠️ 问题(3个需要修改) 1. **.gitea/workflows/preview-deploy.yml 第36-46行**:存在 Tar 路径穿越安全风险 - **问题描述**:在 Python 脚本中解压 tarball 时,代码手动修改了 `member.name` 以去除 `root_prefix`,但未对修改后的路径进行校验。如果恶意构建的 tar 包中包含文件名如 `../../etc/passwd`,在去除前缀后可能保留路径穿越字符,导致文件被解压到工作目录之外。 - **修改建议**:在 `tar.extract` 之前,必须检查 `member.name` 是否包含 `..` 或是否以 `/` 开头(绝对路径)。建议使用 `if ".." in member.name or member.name.startswith("/"): continue` 或抛出异常。 2. **.gitea/workflows/preview-deploy.yml 第181行 & .gitea/workflows/preview-cleanup.yml 第62行**:SSH 连接存在中间人攻击风险 - **问题描述**:在使用 `ssh` 连接时显式使用了 `-o StrictHostKeyChecking=no`。虽然之前执行了 `ssh-keyscan`,但关闭严格主机密钥检查会使连接容易受到中间人攻击,且使得 `known_hosts` 机制失效。 - **修改建议**:移除 `-o StrictHostKeyChecking=no`,依赖 `ssh-keyscan` 写入的 `known_hosts` 文件进行验证。如果担心首次连接问题,应确保 `ssh-keyscan` 成功且指纹正确。 3. **.gitea/workflows/preview-deploy.yml 第168行 & .gitea/workflows/preview-cleanup.yml 第48行**:硬编码敏感的基础设施信息 - **问题描述**:代码中硬编码了默认的 STAGING 服务器 IP 地址 `47.98.113.167`。将真实的公网 IP 地址提交到代码仓库中会暴露基础设施信息,增加被攻击的风险,且不利于后续基础设施的迁移或变更。 - **修改建议**:移除默认值,如果 Secret 缺失则直接报错退出,避免使用硬编码的回退值。 ### 💡 建议(2个可选) 1. **.gitea/workflows/preview-deploy.yml 第242行**:评论查找逻辑较为脆弱 - **建议描述**:查找已有评论的逻辑依赖于字符串 `'预览环境已部署'` 存在且 `'Preview URL'` 不存在。这种基于特定文本内容的匹配方式非常脆弱,一旦评论文案发生微调(如翻译、格式调整),就会导致无法更新评论而重复发布。建议在评论中插入一个隐藏的 HTML 标记(如 `<!-- preview-comment-marker -->`)来唯一标识该评论。 2. **scripts/ci/preview_nginx.conf.template 第1行**:HTTPS 配置与 Workflow 输出不一致 - **建议描述**:Nginx 配置模板中仅启用了 HTTP (80端口) 监听,HTTPS (443端口) 配置块被注释。但在 Workflow 中向用户输出的预览链接是 `https://...`。如果服务器未配置 SSL 或默认重定向,用户访问链接会失败。建议确认环境是否已配置 HTTPS,若未配置,Workflow 输出链接应改为 `http`,或者完善 Nginx 模板以支持 HTTPS。 --- ✅ 格式检查通过 | ❌ 逻辑审查需修改 | ⚠️ 建议关注性能 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-07-17 19:17:35 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->
auto-approve-bot approved these changes 2026-07-17 19:19:57 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。
auto-approve-bot approved these changes 2026-07-17 19:19:57 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。
auto-approve-bot merged commit eecdbf7059 into develop 2026-07-17 19:43:42 +08:00
Sign in to join this conversation.