Gitee Go + Agent 部署 VuePress 静态站实践
约 1760 字大约 6 分钟
布欧-Lewyon
2026-06-04
前言
本文记录一套可复用的 CI/CD 自动部署流程:代码 push 后,由 Gitee Go 完成 VuePress 构建,再通过 主机组 Agent 将静态产物同步到云服务器,并由 Nginx 对外提供访问。
文中路径、主机组名称均为示例,请按自己的环境替换;不包含任何公网地址或站点品牌信息。
1. 整体架构
| 环节 | 工具 | 说明 |
|---|---|---|
| 源码托管 | Gitee | 触发流水线 |
| 构建 | Gitee Go build@nodejs | Node + pnpm + docs:build |
| 制品 | BUILD_ARTIFACT.tar.gz | 打包 docs/.vuepress/dist |
| 部署 | deploy@agent | 在目标机上解压并 rsync |
| 运行 | Nginx | 静态文件 + 可选 API 反代 |
2. 前置条件
2.1 仓库侧
- 流水线配置文件:
.workflow/branch-pipeline.yml(Gitee 图形界面需绑定该文件名,大小写敏感)。 - 构建命令与仓库脚本一致(示例:
pnpm docs:build)。 - 制品路径与 VuePress 输出目录一致:
./docs/.vuepress/dist。
2.2 服务器侧
- 已安装 Gitee 主机组 Agent,状态健康。
- 部署用户(示例:
ubuntu)对站点目录 可写。 - Nginx 已安装,80 端口可访问。
2.3 一次性目录与权限
Agent 以普通用户运行,若站点目录由 root 创建,部署会报 Permission denied:
sudo mkdir -p /var/www/static-site
sudo chown -R ubuntu:ubuntu /var/www/static-site
mkdir -p ~/gitee_go/deploy验证:
touch /var/www/static-site/.test && rm /var/www/static-site/.test && echo OK3. 流水线配置说明
3.1 触发规则
- 推送到非
master分支时自动触发(可按需调整triggers.push)。 - 构建、部署两阶段均
strategy: naturally,构建成功后自动部署。
3.2 构建阶段
Gitee 内置 Node 版本可能偏旧,且 corepack enable 在部分构建机上只读失败。可采用:
- 从镜像站下载 Node 22 二进制到
/tmp并加入PATH。 - 使用
npm install -g pnpm安装 pnpm(避免 corepack 写系统目录)。 pnpm install --frozen-lockfile后执行pnpm docs:build。
构建日志中应看到页面数量与 dist 生成成功;若 Markdown 含未转义的 <>,VuePress 可能解析失败,需在文档中写成 < / >。
制品名必须为流水线配置的 BUILD_ARTIFACT(部署阶段下载的文件名为 BUILD_ARTIFACT.tar.gz,不是 output.tar.gz)。
3.3 部署阶段
要点:
| 配置项 | 说明 |
|---|---|
deploy@agent | 在已绑定 Agent 的主机上执行脚本 |
hostGroupID | 主机组 ID + 主机 UUID |
deployArtifact | 从构建阶段拉取 BUILD_ARTIFACT 到 ~/gitee_go/deploy |
script | 必须用 script: | 多行字符串,不要用 YAML 列表,否则 if/fi 易被平台截断 |
部署脚本核心逻辑:
- 解压制品到临时目录。
find定位dist/index.html(兼容制品目录多一层嵌套)。- 写入前检查目标目录是否可写,不可写则打印
chown提示并失败。 rsync --delete同步到DEPLOY_DIR(示例/var/www/static-site)。- 使用
--no-owner --no-group,避免 rsync 改属主失败。
环境变量 DEPLOY_DIR 可在 Agent 环境或脚本中覆盖,便于多环境复用。
4. Nginx:静态站与既有子路径应用共存
若服务器上 已有历史应用 需挂在子路径(如 /legacy-app/),而新的 VuePress 站占根路径 /,应使用 单一 server 块 + 多个 location,并注意以下坑。
4.1 不要把 server 写在 nginx.conf 的 http{} 里
若主配置里仍有 listen 80; root /var/www/old-app;,会与 sites-enabled 中的站点 争抢 default_server,出现:
- 访问
/仍是旧页面; nginx -t警告conflicting server name "_"。
推荐:nginx.conf 仅保留 include /etc/nginx/sites-enabled/*;,虚拟主机全部放在 sites-available 中。
4.2 推荐 location 结构(示例)
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /var/www/static-site;
index index.html;
location = /legacy-app {
return 301 /legacy-app/;
}
# 静态资源:禁止回退到 index.html,避免 .js 返回 HTML(MIME 报错)
location ^~ /legacy-app/assets/ {
root /var/www;
try_files $uri =404;
}
location ^~ /legacy-app/ {
root /var/www;
try_files $uri $uri/ /legacy-app/index.html;
}
location /api/ {
proxy_pass http://127.0.0.1:8000/api/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location / {
try_files $uri $uri/ /index.html;
}
}说明:
^~:避免博客侧的location ~* \.js$正则抢走子路径下的.js请求。- 子路径前端 若打包时
base为/,挂到子路径会白屏或 MIME 错误;应设置base: '/legacy-app/'后重新 build,或使用独立端口部署旧应用。 - API 多为 POST;用
curlGET 测接口可能 404 或Method not allowed,应以浏览器 Network 为准。
4.3 浏览器缓存与 MIME
若 index.html 已指向 /legacy-app/assets/xxx.js,但浏览器仍请求 /assets/xxx.js,会得到根站点的 HTML,触发:
Expected JavaScript but MIME type was text/html
处理:
- 确认服务器上
curl正确路径返回application/javascript。 - 无痕窗口 + 禁用缓存,或给 script 加
?v=2查询参数强制刷新。 - 确认使用
http://访问(未配置 HTTPS 时不要误用https://)。
5. 部署验收清单
| 检查项 | 命令或方法 | 期望 |
|---|---|---|
| 制品解压 | 部署日志 | 找到 dist/index.html |
| 目录权限 | 部署日志 / touch 测试 | 无 Permission denied |
| 根站 HTML | curl -s http://127.0.0.1/ | head | 含 VuePress 特征 |
| 静态 JS | curl -sI .../assets/*.js | Content-Type: application/javascript |
| Nginx 语法 | nginx -t | 无 conflicting server name |
| 外网访问 | 浏览器无痕 | 根路径为新站,子路径为旧应用 |
6. 常见问题速查
| 现象 | 原因 | 处理 |
|---|---|---|
构建仍跑旧模板 npm install | 平台未绑定仓库 YAML | 恢复 .workflow/branch-pipeline.yml 并在界面重新关联 |
EROFS / corepack 失败 | 构建机 Node 目录只读 | 改用 npm 全局安装 pnpm + 自举 Node 22 |
BUILD_ARTIFACT 找不到 | 制品名或路径不一致 | 对齐 artifacts.path 与 dependArtifact |
| rsync Permission denied | 目录属主为 root | chown 给 Agent 用户 |
| 部署成功但页面是旧站 | Nginx 多 server 冲突 | 删除主配置内旧 server,只保留 sites-enabled |
| 子路径白屏 / MIME | 前端 base 与挂载路径不一致 | 修改 vite.config 的 base 并重新构建上传 |
| API 404 | 路径或方法不对 | 查后端日志;确认 proxy_pass 是否保留 /api 前缀 |
7. 日常发布流程(操作摘要)
- 在本地编辑 Markdown,通过
pnpm docs:dev预览。 git commit并 push 到触发分支。- 在 Gitee Go 查看 构建 → 部署 日志,确认
部署完成: $DEPLOY_DIR。 - 浏览器无痕访问根路径,抽查内页与静态资源。
- 若仅部署失败,可单独 重跑部署阶段,无需完整重建(制品未过期时)。
8. 相关仓库文件(示例)
| 文件 | 用途 |
|---|---|
.workflow/branch-pipeline.yml | 构建 + Agent 部署 |
deploy/nginx.conf | Nginx 模板(根站 + 子路径共存) |
deploy/server-init.sh | 一次性权限初始化 |
deploy/README.md | deploy 目录说明 |
| 运维排错与 Linux 命令 | 常见问题与命令速查 |
以上为一次完整落地后的沉淀:CI 负责可重复构建,Agent 负责原子同步,Nginx 负责路由隔离。扩展新环境时,优先复制流水线与 DEPLOY_DIR,再按验收清单逐项核对即可。
延伸阅读:
