GitHub Actions:个人博客的 CI 流水线设计
lint、单测、E2E、构建、部署、索引重建的流水线编排,以及 artifacts 传递、权限最小化和并发控制
GitHub Actions:个人博客的 CI 流水线设计
流水线的价值不在「能跑」,在「挂了的时候能立刻看出是哪一层的问题」。本站的 CI 分六个 job,每个 job 只做一件事,失败原因一眼可见。
Job 的编排与依赖
jobs:
lint:
runs-on: ubuntu-latest
steps: [...]
vitest:
runs-on: ubuntu-latest
steps: [...]
e2e:
needs: build # 依赖构建产物
deploy:
needs: [vitest, e2e] # 质量门禁
index:
needs: deploy无依赖的 job(lint、vitest、build)并行跑省时间;有依赖的串行。两条铁律:E2E 必须吃构建产物(对 out/ 目录的断言才是对真实产物的断言),部署必须放在测试之后(没有质量门禁的流水线只是个自动 FTP)。
Artifacts 传递构建产物
- uses: actions/upload-artifact@v4
with:
name: site-out
path: out/build job 产出 out/,e2e job 下载它启动静态服务器跑断言,deploy job 下载它推给 Cloudflare Pages。一次构建、三处消费,保证「测过的」和「部署的」是同一份产物——这是很多流水线忽略的一致性问题:测试跑在干净 checkout 上、部署却现场重新构建,两边产物可能不同。
权限最小化
permissions:
contents: readworkflow 级别收紧到 contents: read。部署用的 Cloudflare API token 单独创建,只授 Pages、D1、Vectorize、Workers AI 四项权限,不放账号级 token。泄露爆炸半径取决于 token 权限,这一步的成本是十分钟,收益是睡个安稳觉。
条件执行的索引重建
文章是向量索引的数据源,但不是每次提交都动文章。索引重建 job 用路径过滤:
on:
push:
branches: [main]
paths:
- 'posts/**'
- 'scripts/build-index.mjs'posts/ 或索引脚本变更才触发,其他提交(改样式、改文档)跳过重建,省时间也省 embedding 费用。
并发控制与超时
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true连续 push 时取消排队中的旧 run,只测最新提交。每个 job 设 timeout-minutes,防止悬挂的测试把 run 卡到一小时——E2E 尤其需要,浏览器不退出是常态事故。
失败通知的最后一块拼图
流水线的闭环是「失败必须被看见」。个人项目用不起 Slack 集成,最简做法是给仓库开邮件通知(默认就有),再加上一条纪律:看到红叉当天处理,不留过夜的红——红叉过夜的仓库,CI 很快就会名存实亡。
基于站内文章回答,并标注引用来源
留言
加载中…