GitHub CI/CD 自动化部署

更新于 2026-08-28

为什么很多人的博客写着写着就断更了?除了工作忙,一个隐蔽的罪魁祸首就是「发布流程太有仪式感」:写完两行字,要先本地跑命令打包,再打开 FTP 或者手动敲指令往服务器传,一旦忘了拷某张配图或者本地环境差了一个小版本,整站瞬间白屏。折腾完这一圈,只想把电脑合上发誓下个月再写。

最舒服的写作体验应该是:本地只管码字,敲下 git push 关掉电脑,剩下的编译、打包、上线全部由云端流水线自动搞定

本篇讲解如何用 GitHub Actions 为 RustPress 配置全自动 CI/CD 部署流水线。


一、自动化构建全流程

┌─────────────────┐      git push      ┌─────────────────────────────┐
│  本地写好 Markdown │ ─────────────────> │  GitHub Markdown 源码库(main) │
│ (source/*.md)   │                    └──────────────┬──────────────┘
└─────────────────┘                                   │ 触发 Actions
                                                      ▼
┌────────────────────────────────────────────────────────────────────┐
│                    GitHub Actions 自动化流水线                      │
│                                                                    │
│  1. 拉取完整 Git Log(精准提取文章最后修改时间戳)                   │
│  2. 自动配置 Rust 环境并缓存安装产物                                 │
│  3. 生产编译(rustpress -m source build -o public)                │
│  4. 同步 CNAME / ads.txt / _redirects 等根目录资产                 │
│  5. 自动发布到 GitHub Pages(单仓库分支 或 独立公开仓库)          │
└─────────────────────────────────┬──────────────────────────────────┘
                                  │ 自动发布完毕
                                  ▼
                    ┌───────────────────────────┐
                    │ 线上即刻访问:yishulun.com  │
                    └───────────────────────────┘

二、部署方案选型:方案 A vs 方案 B

根据你的仓库权限管理偏好多仓库规划,RustPress 提供了两种标准的部署方案。请先根据以下对比选择适合你的形态:

方案 A:单仓库双分支模式(推荐 · 极简)

  • 适用场景:绝大多数个人博客、技术主页。
  • 源码存放:本仓库 main 分支。
  • 产物存放:本仓库 gh-pages 分支。
  • 密钥配置完全免配置(直接使用 GitHub 内置 GITHUB_TOKEN)。
  • 配置复杂度:⭐(一键复制 YAML 即可上线)。

方案 B:双仓库分离模式(源码私有 + 产物公开)

  • 适用场景:原稿/草稿保密,或主站需独立发布到 username.github.io
  • 源码存放:独立私有仓库(如 my-blog-source)。
  • 产物存放:独立公开仓库(如 username.github.io)。
  • 密钥配置需要配置(生成并配置 PERSONAL_ACCESS_TOKEN)。
  • 配置复杂度:⭐⭐⭐(需创建跨仓库 Personal Access Token)。

三、方案 A:单仓库双分支部署(推荐 · 零密钥极简)

方案特点:源码放在 main 分支,GitHub Actions 编译后自动推送到本仓库的 gh-pages 分支。无需申请任何个人密钥,开箱即用。

步骤 1:创建工作流文件

在博客仓库根目录下创建 .github/workflows/deploy.yml,粘贴以下完整配置:

name: Deploy RustPress Blog

on:
  # push 到 main 分支时自动触发
  push:
    branches: [main]
  # 支持在 GitHub 网页上点击 "Run workflow" 手动触发
  workflow_dispatch:

# 赋予工作流向仓库分支写入部署产物的权限
permissions:
  contents: write

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
      # 1. 检出仓库代码(fetch-depth: 0 必加,拉取完整历史以精准识别文章修改时间)
      - name: Checkout Source Code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      # 2. 准备 Rust 工具链
      - name: Setup Rust Toolchain
        uses: dtolnay/rust-toolchain@stable

      # 3. 启用 Rust 编译缓存(大幅提升后续构建速度)
      - name: Setup Rust Cache
        uses: Swatinem/rust-cache@v2

      # 4. 缓存 RustPress 二进制与 Cargo 索引
      - name: Cache Cargo Binaries
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
          key: ${{ runner.os }}-cargo-rustpress-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-rustpress-

      # 5. 安装最新版 RustPress CLI
      - name: Install RustPress CLI
        run: |
          if ! command -v rustpress &> /dev/null; then
            cargo install rustpress --locked
          fi

      # 6. 校验版本
      - name: Verify RustPress Version
        run: rustpress -V

      # 7. 生产环境全量构建(静态文件输出到 public 目录)
      - name: Build Static Site
        run: rustpress -m source build -o public

      # 8. 拷贝根目录资产(CNAME、谷歌广告认证、重定向规则等)
      - name: Copy Root Static Assets
        run: |
          cp source/CNAME public/ 2>/dev/null || true
          cp source/ads.txt public/ 2>/dev/null || true
          cp source/_redirects public/_redirects 2>/dev/null || true

      # 9. 部署发布到本仓库的 gh-pages 分支
      - name: Deploy to gh-pages Branch
        uses: peaceiris/actions-gh-pages@v4
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./public
          publish_branch: gh-pages
          commit_message: "docs: auto deploy with RustPress [skip ci]"

步骤 2:在仓库开启 GitHub Pages

  1. 提交并推送代码后,进入当前仓库的 Settings -> Pages
  2. Build and deployment 下:
    • Source:选择 Deploy from a branch
    • Branch:选择 gh-pages,目录保持 / (root)
  3. 点击 Save 保存即可。

四、方案 B:双仓库分离部署(私有源码 + 公开静态库)

方案特点:Markdown 源码存放在私有仓库,编译生成的 HTML 产物自动推送到另一个公开仓库(例如你的主站 username.github.io)。

步骤 1:生成 Personal Access Token (PAT)

因为需要将编译产物跨仓库推送到另一个仓库,需要为 GitHub Actions 提供跨库写入权限:

  1. 登录 GitHub,点击右上角头像 -> Settings -> 最底部 Developer Settings
  2. 选择 Personal access tokens -> Tokens (classic)
  3. 点击 Generate new token (classic)
    • Note:填入 RustPress Deploy Token
    • Expiration:建议选择 No expiration(或按需设定期限);
    • Scopes(权限):勾选 repo(包含所有子项,用于读写仓库);
  4. 点击底部 Generate token立即复制生成的 Token 字符串(刷新页面后将无法再次查看)。

步骤 2:在源码私有仓库中配置 Secret

  1. 打开存放 Markdown 的源码私有仓库
  2. 进入 Settings -> Secrets and variables -> Actions
  3. 点击 New repository secret
    • NamePERSONAL_ACCESS_TOKEN
    • Secret:粘贴刚才复制的 Token;
  4. 点击 Add secret 保存。

步骤 3:创建工作流文件

源码私有仓库根目录下创建 .github/workflows/deploy.yml,粘贴以下完整配置(记得将第 9 步的用户名和仓库名替换为你自己的):

name: Deploy RustPress Blog to External Repo

on:
  push:
    branches: [main]
  workflow_dispatch:

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
      # 1. 检出源码(fetch-depth: 0 必加,拉取完整提交历史)
      - name: Checkout Source Code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      # 2. 准备 Rust 工具链
      - name: Setup Rust Toolchain
        uses: dtolnay/rust-toolchain@stable

      # 3. 启用 Rust 编译缓存
      - name: Setup Rust Cache
        uses: Swatinem/rust-cache@v2

      # 4. 缓存 Cargo 二进制产物
      - name: Cache Cargo Binaries
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
          key: ${{ runner.os }}-cargo-rustpress-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-rustpress-

      # 5. 安装 RustPress CLI
      - name: Install RustPress CLI
        run: |
          if ! command -v rustpress &> /dev/null; then
            cargo install rustpress --locked
          fi

      # 6. 校验版本
      - name: Verify RustPress Version
        run: rustpress -V

      # 7. 生产环境全量构建
      - name: Build Static Site
        run: rustpress -m source build -o public

      # 8. 拷贝根目录资产(CNAME、谷歌广告认证、重定向规则)
      - name: Copy Root Static Assets
        run: |
          cp source/CNAME public/ 2>/dev/null || true
          cp source/ads.txt public/ 2>/dev/null || true
          cp source/_redirects public/_redirects 2>/dev/null || true

      # 9. 跨仓库推送到目标公开仓库(如 username.github.io)
      - name: Deploy to External GitHub Pages Repo
        uses: cpina/[email protected]
        env:
          API_TOKEN_GITHUB: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
        with:
          source-directory: public/
          destination-github-username: <your-github-username> # 替换为你的 GitHub 用户名
          destination-repository-name: <your-github-username>.github.io # 替换为目标公开仓库名
          user-email: <your-email>@example.com # 替换为你自己的 Git 邮箱
          target-branch: "main"

步骤 4:在目标公开仓库开启 Pages 托管

  1. 打开目标公开仓库(如 username.github.io);
  2. 进入 Settings -> Pages
  3. Branch 选择 main,目录选 / (root),点击 Save

五、关键根目录资产说明 (CNAME / ads.txt)

在构建流水线的第 8 步中,会自动同步以下根目录特殊资产:

  • source/CNAME:若绑定了个性化独立域名(如 yishulun.com),直接在 source/ 下放置 CNAME 文件,构建时会自动拷入 public/ 根目录,防止每次构建覆盖自定义域名配置。
  • source/ads.txt:若接入了 Google AdSense,放置于 source/ads.txt 即可自动同步至全站根路径 https://yourdomain.com/ads.txt
  • source/_redirects:若需要配置 301/302 URL 别名跳转规则,放置于 source/_redirects 同样会自动发布。

六、验证部署与排错指南

完成配置后,在本地终端执行一次测试提交:

git add .
git commit -m "feat: setup rustpress github actions ci-cd"
git push origin main

1. 验证上线

  1. 访问 GitHub 仓库的 Actions 标签页,查看正在运行的构建任务;
  2. 约 30~50 秒后,任务显示绿色对勾(Success);
  3. 浏览器访问你的 GitHub Pages 域名,网站已成功发布。

2. 常见问题排查

  • 文章修改时间不准确?:请确认第 1 步中的 fetch-depth: 0 是否配置。如果拉取深度为 1,Git 历史被截断,RustPress 将无法从 Git Log 提取真实的修改时间戳。
  • 方案 A 提示 403 权限不足?:请检查 YAML 顶层是否声明了 permissions: contents: write
  • 方案 B 提示 Token 认证失败?:请检查 Secret 名称是否与 YAML 中的 PERSONAL_ACCESS_TOKEN 完全一致,且 Token 是否具备 repo 权限范围。

辩证视角:云端流水线 vs 本地构建底牌
云端 Actions 托管能杜绝本地环境污染、统一编译基准,支持多设备随时提交;但在极端断网或平台 Runner 排队时,完全依赖云端会丧失即时发布的自主权。
边界原则:常态化写作与发布托付给 GitHub Actions 保证一致性;本地始终保留一份可执行的 rustpress build 作为离线应急底牌。

至此,自动化流水线完全通畅。下一篇,我们来聊聊如何接入 Cloudflare,让博客在全球节点极速响应,同时发完新文章不用手动去后台清缓存

金石碼农

金石碼农

大学计算机讲师,腾讯云最具价值专家(TVP),《小程序从0到1》《微信小游戏开发》作者,微信学堂讲师,极客时间荣誉讲师。公众号:艺述论。

北京, 中国

扫一扫,添加作者微信

微信二维码

评论

登录 GitHub 后即可发表评论
加载评论中...