为什么很多人的博客写着写着就断更了?除了工作忙,一个隐蔽的罪魁祸首就是「发布流程太有仪式感」:写完两行字,要先本地跑命令打包,再打开 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
- 提交并推送代码后,进入当前仓库的 Settings -> Pages;
- 在 Build and deployment 下:
- Source:选择
Deploy from a branch; - Branch:选择
gh-pages,目录保持/ (root);
- Source:选择
- 点击 Save 保存即可。
四、方案 B:双仓库分离部署(私有源码 + 公开静态库)
方案特点:Markdown 源码存放在私有仓库,编译生成的 HTML 产物自动推送到另一个公开仓库(例如你的主站
username.github.io)。
步骤 1:生成 Personal Access Token (PAT)
因为需要将编译产物跨仓库推送到另一个仓库,需要为 GitHub Actions 提供跨库写入权限:
- 登录 GitHub,点击右上角头像 -> Settings -> 最底部 Developer Settings;
- 选择 Personal access tokens -> Tokens (classic);
- 点击 Generate new token (classic):
- Note:填入
RustPress Deploy Token; - Expiration:建议选择
No expiration(或按需设定期限); - Scopes(权限):勾选
repo(包含所有子项,用于读写仓库);
- Note:填入
- 点击底部 Generate token,立即复制生成的 Token 字符串(刷新页面后将无法再次查看)。
步骤 2:在源码私有仓库中配置 Secret
- 打开存放 Markdown 的源码私有仓库;
- 进入 Settings -> Secrets and variables -> Actions;
- 点击 New repository secret:
- Name:
PERSONAL_ACCESS_TOKEN - Secret:粘贴刚才复制的 Token;
- Name:
- 点击 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 托管
- 打开目标公开仓库(如
username.github.io); - 进入 Settings -> Pages;
- 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. 验证上线
- 访问 GitHub 仓库的 Actions 标签页,查看正在运行的构建任务;
- 约 30~50 秒后,任务显示绿色对勾(
Success); - 浏览器访问你的 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,让博客在全球节点极速响应,同时发完新文章不用手动去后台清缓存。