自动化部署流水线

学习目标

  • 理解 GitHub Actions 的基本概念
  • 掌握三分支策略的同步机制
  • 学会配置 GitHub Pages

前置条件

1. 三分支策略回顾

main ── 日常编辑笔记
  │
  ▼  sync-main-to-v5.yml
v5 ──── Quartz 构建环境
  │
  ▼  deploy.yml
gh-pages ── 静态文件 → GitHub Pages

为什么用三个分支?

方案优点缺点
单分支简单仓库混入构建工具文件,Obsidian 中看到 node_modules/
三分支main 保持纯净,构建和发布分离需要同步机制(用 Actions 解决)

2. 选择部署模式

两种模式的权限和工作流结构不同:

模式mainv5gh-pages适用场景
普通版无分支保护无分支保护无分支保护个人仓库、无 PAT
PAT 规则版要求 PR要求 PR要求 PR多人协作、限制直接更新

普通版用一个工作流完成同步、构建和发布,不需要 PAT。PAT 规则版让 main → v5v5 → gh-pages 分为两个工作流,因此需要 PAT 触发后续工作流并绕过规则集。

3. 普通版:三个分支都不启用保护

3.1 分支设置

Settings → Rules → Rulesets 中,不为 mainv5gh-pages 创建或启用任何匹配规则。所有具备写入权限的协作者都可直接推送这三个分支。

不需要创建 PERSONAL_TOKEN。在仓库 Settings → Actions → General → Workflow permissions 中选择 Read and write permissions。这样工作流自带的 GITHUB_TOKEN 才能推送 v5gh-pages

3.2 main:同步工作流

将下列文件保存为 main/.github/workflows/publish.yml

name: Sync, Build and Deploy
 
on:
  push:
    branches: [main]
  workflow_dispatch:
 
permissions:
  contents: write
 
jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/checkout@v4
        with:
          ref: v5
          path: v5-branch
      - uses: actions/setup-node@v4
        with:
          node-version: 22
      - name: Sync content
        run: |
          for dir in section0 section1 ... appendix image; do
            rsync -a --delete "$dir/" "v5-branch/content/$dir/"
          done
          cp markdown格式总结.md v5-branch/content/ 2>/dev/null || true
      - name: Commit and push to v5
        run: |
          cd v5-branch
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          git add content/
          git diff --staged --quiet || git commit -m "sync: 从 main 同步内容更新"
          git push origin HEAD:v5
      - name: Build Quartz
        working-directory: v5-branch
        run: |
          npm ci
          npx quartz plugin install
          npx quartz build
      - name: Deploy to gh-pages
        uses: peaceiris/actions-gh-pages@v4
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: v5-branch/public
          publish_branch: gh-pages

该工作流创建的 v5 推送不会再触发其他工作流,但构建和发布已经在同一个 job 中完成,因此不受影响。

3.3 v5:分支内容

v5 保存 Quartz 引擎、quartz.config.yaml 和被同步的 content/。普通版不需要在 v5 保存部署 YAML,因为构建由 main 上的 publish.ymlv5-branch/ 工作目录中执行。

直接修改 v5(例如更新 quartz.config.yaml)后,需手动运行或重新推送 main 上的 publish.yml 才会发布;若希望每次 v5 推送都自动发布,请使用下一节的 PAT 规则版。

3.4 gh-pages:Pages 设置

gh-pages 不需要保存工作流文件;它只接收 v5 构建产物。在 Settings → Pages 中选择:

  1. SourceDeploy from a branch
  2. Branchgh-pages
  3. Folder/ (root)

4. PAT 规则版:三个分支都要求通过 PR

4.1 获取 PAT 并添加规则

在一个匹配 mainv5gh-pages 的 Active ruleset 中,对每个分支启用:

  • Require a pull request before merging
  • Restrict deletions
  • Block force pushes

在同一 ruleset 的 Bypass list 中,添加 Repository admin 并选择 Always allow。不要添加 WriteMaintain,否则普通协作者也能绕过 PR 规则。

创建 PAT:GitHub 右上角头像 → SettingsDeveloper settingsPersonal access tokensTokens (classic)Generate new token (classic)。选择合理的过期时间,勾选 repo scope 后生成并立即复制。

在仓库 Settings → Secrets and variables → Actions 中新建 repository secret:名称为 PERSONAL_TOKEN,值为刚生成的 PAT。PAT 认证时代表创建它的管理员账号;github-actions[bot] 不是需要加入 bypass 的独立账号。

4.2 main:同步工作流

将下列文件保存为 main/.github/workflows/sync-main-to-v5.yml

name: Sync main → v5
 
on:
  push:
    branches: [main]
 
permissions:
  contents: read
 
jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
          persist-credentials: false
      - uses: actions/checkout@v4
        with:
          ref: v5
          path: v5-branch
          persist-credentials: false
      - name: Sync content
        run: |
          for dir in section0 section1 ... appendix image; do
            rsync -a --delete "$dir/" "v5-branch/content/$dir/"
          done
          cp markdown格式总结.md v5-branch/content/ 2>/dev/null || true
      - name: Commit and push to v5
        env:
          PERSONAL_TOKEN: ${{ secrets.PERSONAL_TOKEN }}
        run: |
          cd v5-branch
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          git add content/
          git diff --staged --quiet || git commit -m "sync: 从 main 同步内容更新"
          git push "https://x-access-token:${PERSONAL_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" HEAD:v5

两个 checkout 的 persist-credentials: false 不能省略。否则 actions/checkout 会保存默认 GITHUB_TOKEN 的认证 header;即使推送 URL 写了 PAT,Git 也可能仍以 github-actions[bot] 身份请求,从而收到 GH013

4.3 v5:构建和发布工作流

将下列文件保存为 v5/.github/workflows/deploy.yml

name: Build and Deploy to GitHub Pages
 
on:
  push:
    branches: [v5]
 
permissions:
  contents: read
 
concurrency:
  group: pages
  cancel-in-progress: false
 
jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false
      - uses: actions/setup-node@v4
        with:
          node-version: 22
      - run: npm ci
      - run: npx quartz plugin install
      - run: npx quartz build
      - uses: peaceiris/actions-gh-pages@v4
        with:
          github_token: ${{ secrets.PERSONAL_TOKEN }}
          publish_dir: ./public
          publish_branch: gh-pages

PERSONAL_TOKEN 所代表的管理员身份会绕过 gh-pages 的 PR 规则;persist-credentials: false 可避免默认 GITHUB_TOKEN 干扰 Git 认证。

4.4 gh-pages:Pages 和保护设置

gh-pages 不包含工作流 YAML。它同时承担两项设置:

  1. 在 ruleset 中启用 PR、删除限制与禁止强制推送;
  2. Settings → Pages 中作为 Deploy from a branch 的发布源,目录为 / (root)

自动化通过管理员 PAT 更新 gh-pages;成员仍必须经由 PR 修改这个分支。

为什么不直接用 actions/deploy-pages

GitHub 官方的 deploy-pages 需要 github-pages 环境。peaceiris/actions-gh-pages 则直接将构建产物推送到 gh-pages,适合本教程的分支发布模式。

5. 同步范围

目录/文件同步?说明
section0/ ~ section12/教程章节
appendix/附录
image/图片资源
markdown格式总结.md根目录的笔记
README.md仓库说明
Clippings/网页剪藏
template/笔记模板
.doc/内部文档

6. 完整发布流程

# 1. 编辑笔记(在 main 分支)
git add .
git commit -m "更新笔记"
git push origin main
 
# 2. 等待 Actions 自动执行
#    普通版:publish.yml
#    PAT 规则版:sync-main-to-v5.yml → deploy.yml
 
# 3. 访问网站
#    https://用户名.github.io/仓库名/

普通版中,直接修改 v5(例如更新 quartz.config.yaml)后,可在 Actions 手动运行 mainpublish.yml;PAT 规则版则会在推送 v5 后自动发布。两种模式通常都在 2-3 分钟内完成网站更新。

扩展阅读

常见问题

Q: Actions 报错 “Branch not allowed to deploy”?

使用 peaceiris/actions-gh-pages 替代 actions/deploy-pages,或在仓库 Settings → Environments 中删除 github-pages 环境。

Q: 同步工作流没有触发?

确认工作流文件在 main 分支的 .github/workflows/ 目录下,且 .gitignore 没有忽略 .github/workflows/

Q: 工作流报 GH013: Changes must be made through a pull request

按以下顺序检查:

  1. 打开错误日志给出的 rules?ref=... 链接,确认目标分支只命中了预期的 ruleset;
  2. 确认该 ruleset 的 Repository admin bypass 是 Always allow,而不是 For pull requests only
  3. 确认 PERSONAL_TOKEN 是管理员账号创建的 Classic PAT,并有 repo scope;
  4. 确认执行 Git 推送前的每个 actions/checkout 都设置了 persist-credentials: false
  5. 确认推送命令或部署 action 实际传入了 PERSONAL_TOKEN,而不是默认 GITHUB_TOKEN

Q: 网站访问 404?

  • 确认 Actions 已完成(绿色勾号)
  • 确认 Pages 设置中选择了 gh-pages 分支
  • 硬刷新浏览器(Ctrl+F5)

练习任务

  1. 在 GitHub 仓库中查看 Actions 运行情况
  2. 尝试推送一次 main 分支,观察两个工作流的执行顺序
  3. 确认网站能正常访问

验收清单

  • 理解三分支策略的工作流程
  • 知道两个工作流各自的职责
  • 完成了 GitHub Pages 设置
  • 成功发布了一次网站更新