2026年8月8日 星期六 晴→雷雨

此刻窗外正在打雷,即将到来的台风风级很大。

今天下午和晚上都在重构博客的部署系统,最终从 Bitbucket Pipelines 迁移到了 GitHub Actions。

问题背景

我大概有 3500+ 篇博客,历史部署经历过三个阶段:

阶段一:本地编译,推静态文件到 Git 本地 hugo --gc 编译成 HTML,连同源文件一起推 git 仓库。一开始没事,后来 git 仓库越来越大,最终 overflow。

阶段二:Vercel 构建 改为 Vercel 原生构建,本地只推源文件。Vercel 有时 1‑2 分钟成功,有时直接跑到 45m 被杀掉。原因是 Vercel 构建缓存最大 1GB,超过或长时间不部署会被驱逐,触发全量冷构建。4000 页面属于中大型 Hugo 站点,冷构建压力大,日志滚动到无响应,超时被杀。

阶段三:Bitbucket Pipelines 构建 + Vercel 托管静态文件 构建放到 Bitbucket(2x 内存,4GB),hugo --gc 后把 public/ 产物通过 Vercel CLI 上传。Vercel 只做文件分发,不跑编译。这个方案当天就遇到了问题:上传 4473 个文件逐个请求,网络通畅时 2 分钟,堵车时 9 分钟+。而且 Bitbucket 免费版每月只有 50 构建分钟,调试几次后直接耗尽。

最终方案:GitHub Actions

免费版私有仓库 2000 分钟/月,是 Bitbucket 的 40 倍。公共仓库更是无限分钟。

1. 工作流文件

创建 .github/workflows/deploy.yml,逻辑与之前的 Bitbucket pipeline 一致:

name: Build & Deploy to Vercel

on:
  push:
    branches: [master]
  workflow_dispatch: # 支持手动触发

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest # 4GB 内存,够用
    steps:
      - uses: actions/checkout@v4

      - name: Install Hugo
        run: |
          wget -q "https://github.com/gohugoio/hugo/releases/download/v0.101.0/hugo_extended_0.101.0_Linux-64bit.tar.gz" -O /tmp/hugo.tar.gz
          tar -xzf /tmp/hugo.tar.gz -C /usr/local/bin/ hugo
          hugo version          

      - name: Build site
        env:
          HUGO_CACHEDIR: ${{ github.workspace }}/.hugo_cache
        run: hugo --gc

      - name: Install Vercel CLI
        run: npm install -g vercel

      # 配 project 设置:buildCommand: null, outputDirectory: "."
      - name: Configure Vercel project
        run: ...  # 通过 API 配置

      - name: Deploy to Vercel
        run: |
          vercel ./public --prod --archive=tgz \
            --token=$VERCEL_TOKEN --scope=$VERCEL_ORG_ID --project=$VERCEL_PROJECT_ID          

2. 关键优化:--archive=tgz

vercel ./public --prod 默认把 4473 个文件逐个上传,每个文件一次 HTTP 请求。加 --archive=tgz 后,Vercel CLI 将全部文件打包成单个 tgz 上传,一次请求搞定。Vercel 官方文档明确说"当部署包含数千个文件时使用此选项"。

3. Vercel 端配置

与 Bitbucket 方案时一致,不需要改动:

  • 构建命令为空(buildCommand: null
  • 输出目录为 .(上传的目录就是构建产物)

4. 仓库变量

在 GitHub 仓库 Settings → Secrets and variables → Actions 中配置:

变量名 说明
VERCEL_TOKEN Vercel 账号 Token
VERCEL_ORG_ID Team ID
VERCEL_PROJECT_ID 项目 ID

踩坑记录

问题 原因 修复
Vercel CLI --org 报错 58 版本弃用 --org 改为 --scope
找不到 public 输出目录 Vercel 收到文件后又跑构建 --prebuilt 参数
--prebuilt 需要 .vercel/output 结构 --prebuilt 期望 vercel build 格式 改用 API 配置项目:buildCommand: null + outputDirectory: ".",不加 --prebuilt 直部署
上传 4473 个文件耗时 2~9+ 分钟不稳定 逐个文件 HTTP 上传,网络波动影响大 --archive=tgz 打包为单文件上传
Bitbucket 免费版构建分钟耗尽 每月 50 分钟,调试几次就用完 迁移到 GitHub Actions(2000 分钟/月)
GitHub 无法连接 国内网络环境 Clash 代理 + git 只对 github.com 设代理,不影响公司内网

最终效果

  • 本地编写 → git push → GitHub Actions 自动构建(Hugo 0.101.0,4GB runner,15s)→ --archive=tgz 打包上传 Vercel(几十秒)
  • 不再受 Vercel 构建缓存驱逐影响,构建时间稳定
  • 不再受 CI 分钟配额限制,2000 分钟/月随便用
  • 本地不再推 public/ 目录,git 仓库大幅缩小
  • 部署流程完全通过 git push 触发,写文章的工作流没变

总结

从 Vercel 构建 → Bitbucket Pipelines → GitHub Actions,每次迁移都是在解决上一个方案的瓶颈。最终选择 GitHub Actions 的理由很硬:私有仓库 2000 分钟/月、4GB 免费 runner 够用、与 Vercel 之间的网络路径稳定。加上 --archive=tgz 解决了文件上传的瓶颈,整个部署链路不再有不可控的环节。

希望靠谱吧,以后还是混github。