CI/CD 基础:持续集成与持续部署的核心逻辑
聊到企业级无障碍 CI 测试,第一个绕不开的就是 CI/CD。我知道很多刚入行的朋友一听到这几个缩写就头大,觉得是什么高大上的概念。其实说白了,就是「让机器替你干活,而且干得又快又稳」。我从 2016 年开始接触 CI/CD,踩过坑也填过坑,今天就把最实用的那部分掰开揉碎讲给你听。
什么是 CI?什么是 CD?
我先给个最直白的说法。
持续集成(Continuous Integration,CI)—— 你每次把代码 push 到仓库,自动触发一次构建、跑测试、检查代码质量。它不关心最终部署到哪,只关心「代码合进来之后,有没有搞坏东西」。
持续部署(Continuous Deployment,CD)—— 在 CI 通过之后,自动把产物部署到测试环境、预发环境、甚至生产环境。
两个概念经常捆绑出现,但咱们做无障碍测试的时候,重点关注的是 CI 阶段。因为无障碍检查必须在每次代码变更时快速跑完,才能及时发现问题。我刚开始带团队的时候,曾经把无障碍检查放在手动触发阶段,结果开发合代码后三天才发现按钮没有标签……改起来代价很大。
流水线架构:到底长什么样?
一个标准的 CI/CD 流水线,通常包含下面几个阶段。我用自己项目里的真实例子给你梳理一下。
| 阶段 | 做什么 | 常用工具 | 无障碍相关要点 |
|---|---|---|---|
| 代码检出 | 拉取最新代码 | Git checkout | 无特殊 |
| 代码检查 | 静态分析、lint | ESLint, StyleLint | 自定义 lint 规则确保语义化标签 |
| 测试 | 单元测试、集成测试 | Jest, Playwright | 集成 axe-core 做无障碍断言 |
| 构建 | 打包编译 | Webpack, Vite | 确保 source map 保留 |
| 部署测试环境 | 发布到 staging | Docker, Kubernetes | 部署后运行无障碍快照对比 |
| 审批(可选) | 人工或自动门禁 | GitLab approval | 无障碍违规数超过阈值则阻止合并 |
| 生产部署 | 上线 | 滚动更新、蓝绿部署 | 生产环境同样配无障碍监测 |
这里面最核心的是「测试」阶段。咱们的无障碍 CI 就是嵌套在这条流水线里的。举个例子,我去年做一个金融项目的无障碍 CI,每次 push 都会自动跑 Playwright + axe-core 扫描,如果发现三个以上严重违规,流水线直接红掉,合并按钮都灰了。开发跟我说,「你们 CI 太狠了」,但上线后再也没有收到过残障用户的投诉。
常见 CI/CD 工具怎么选?
现在市面上的 CI/CD 工具很多,我按自己的使用经验排个序。注意,没有的好坏,只有适不适合你的团队规模。
- Jenkins:老牌选手,插件生态最丰富。但我个人不建议小团队自己搭 Jenkins,维护成本太高。我 2018 年在上一家创业公司维护过一套 Jenkins,光插件兼容问题就折腾了两周。
- GitLab CI:如果你用 GitLab,那直接用它内置的 CI 最省事。.gitlab-ci.yml 文件配置,天然支持合并请求一键运行。我在现在的团队就用的这个,省了一个独立 CI 服务器的钱。
- GitHub Actions:目前最流行,市场占有率最高。配置简单,市场里现成的 action 多,比如 axe-action 把无障碍检查包装成一个步骤。如果你是个人项目或中小团队,我建议从 GitHub Actions 入手。
- Travis CI / CircleCI:这两家风格类似,都是云服务。CircleCI 的缓存机制做得不错,适合构建产物大的场景。
不要盲目追新工具。选你现有代码托管平台自带的那一个。比如你在 GitLab 上,就用 GitLab CI;你在 GitHub 上,就用 Actions。少一套系统少一个故障点。
一条完整的无障碍 CI 流水线长什么样?
我来画一个最典型的流程,也是我们课程后面实战部分会落地的方案。你看一眼就明白整体逻辑了。
嗯,流程其实不复杂。关键点在于「阈值」这一步。你想想看,如果一次扫描出 200 个轻微违规,全部阻断会让团队崩溃。所以咱们得设置合理的阈值。我一般这样设:严重违规数 ≥ 1 直接红;中等违规数 ≥ 5 警告但允许通过(人工审核);轻微违规不计入。
配置示例:一个最简单的 GitHub Actions 无障碍 CI
光说理论不行,给你看一段真正能用的代码。这是我一个开源项目里用的配置,去掉了一些敏感信息。
name: A11y CI
on: [push, pull_request]
jobs:
a11y-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Run accessibility scan
run: npx axe --exit --threshold-major=0 --threshold-critical=0 --dir ./dist
这里 --exit 参数很关键。它表示如果扫描到违规,命令返回非 0 码,CI 就会标红。我早期没加这个参数,结果流水线永远绿油油,一直以为是完美通过……后来才发现 axe 默认不 exit。这个坑让我印象深刻。
千万不要把无障碍检查放到「手动触发」这一步。我有一次在项目里给了一个按钮叫做「点击触发无障碍检测」,结果上线两个月都没人点。后来改成自动触发 push 事件后,当天就发现了 17 个缺失标签的问题。记住——自动触发是 CI 的灵魂。
流水线里的「门禁」该怎么设计?
很多团队在 CI 里跑无障碍检查,但跑完只是发一个通知,不阻止合并。我个人觉得,这种做法等于没做。你想想看,如果开发者看到报告只是「建议修改」,大概率会忽略——反正工期紧。
所以我的建议是:设置分级门禁。
- 阻断级(Blocking):严重违规,比如缺少表单 label、图片无 alt、颜色对比度低于 3:1。一旦出现,流水线直接失败,合并请求不能通过。
- 警告级(Warning):中等违规,比如某些按钮焦点顺序不太合理。流水线通过,但会在 PR 评论区留言,并给开发者 24 小时处理时间。
- 信息级(Info):轻微问题,比如冗余的 aria 属性。只记录报告,不做阻断。
我曾经在一个实际项目里实施过这套方案,头两周开发有些抵触,觉得「太严格了」。但后来他们发现,因为没有累积技术债,项目后期无障碍回归测试几乎没有 false positive,反而节省了大量时间。这就是规矩的好处。
常见工具速查表
最后给你一个快速参考表,方便以后选型时查阅。这些工具我都实际使用过,不是纸上谈兵。
| 工具 | 类型 | 适合场景 | 我的个人评价 |
|---|---|---|---|
| Jenkins | 自托管 | 大型企业、复杂流水线 | 灵活但重,维护成本高 |
| GitLab CI | 内置 | GitLab 用户 | 集成度高,配置简洁 |
| GitHub Actions | 云服务 | 中小团队、开源项目 | 生态好,社区 action 多 |
| CircleCI | 云服务 | 需要快速缓存的项目 | 速度优秀,但免费额度有限 |
| Travis CI | 云服务 | 历史项目、小团队 | 逐渐被 GitHub Actions 替代 |
CI/CD 不是玄学,它就是「自动拉代码 → 跑检查 → 给结果 → 阻止问题代码进入主线」。无障碍 CI 就是把「跑检查」这一步换成无障碍扫描工具。搞懂了流水线,后面的实战课就能直接上手。