4. 搭建 CI 环境:GitHub Actions / GitLab CI / Jenkins 选择与配置
聊到无障碍 CI 测试,第一步不是写代码,而是选一个靠谱的“跑腿工具”。这些年我经历过三种主流 CI 平台的“换车”,从自建 Jenkins 到拥抱 GitLab CI,再到给客户搭 GitHub Actions,感受很深。
选哪个?其实没有唯一答案。要看你的团队规模、技术栈、还有运维能力。我先把结论放在前面:
- GitHub Actions:最适合开源项目,配置简单,市场插件丰富
- GitLab CI:私有化部署首选,安全要求高的场景很香
- Jenkins:老牌王者,定制化极强,但维护成本确实高
核心观点:无障碍测试对 CI 的要求其实不高,关键是“容器化”与“可观测性”。不管选哪个平台,能跑 Node、能访问浏览器环境、能输出报告,就够了。
4.1 为什么 CI 环境对无障碍测试至关重要?
我之前在项目中见过这样的情况:开发在本地跑 axe-core 全绿,一上线生产,用户用屏幕阅读器就崩了。为什么?因为本地环境和 CI 环境不一致,有的依赖没装、有的配置漏了。
使用 CI 能解决三个痛点:
- 一致性:每次都在干净容器里跑,结果可复现
- 自动化:Push 代码自动触发,不用人工记着跑
- 拦截:无障碍问题不修,合并按钮就变灰
说白了,CI 是防止“无障碍债务”堆积的第一道防线。你想想看,一个按钮缺了 aria-label,本地测试容易漏,但 CI 里加了规则,一抓一个准。
4.2 三大 CI 平台对比
我整理了一张表,帮你快速做决策。注意看“可扩展性”和“维护成本”这两列,很多团队踩的坑都在这里。
| 特性 | GitHub Actions | GitLab CI | Jenkins |
|---|---|---|---|
| 集成度 | 与 GitHub 深度绑定 | 与 GitLab 生态一体 | 独立部署,需插件集成 |
| 配置难度 | 低(YAML 简单) | 中(关键词较多) | 高(需 Groovy 脚本) |
| 可扩展性 | Marketplace 插件多 | 自定义 Job 灵活 | 插件生态最丰富 |
| 维护成本 | 几乎零维护(SaaS) | 自托管需运维 | 高(插件升级、安全补丁) |
| 无障碍测试适合度 | ★★★★★ | ★★★★☆ | ★★★☆☆ |
我的建议:如果你用 GitHub,直接上 Actions。如果你公司有自建 GitLab,选 GitLab CI。只有当你需要深度定制 pipeline、或者跑大规模并发测试时,才考虑 Jenkins。
4.3 无障碍测试的特殊配置:别忘“浏览器”
嗯,这里要注意一个坑。无障碍测试通常依赖 Puppeteer 或 Playwright 这类无头浏览器工具。在 CI 环境里,你需要确保有完整的浏览器运行环境。
我个人习惯用 Docker 镜像来统一环境。比如在 GitHub Actions 里,直接指定 ubuntu-latest 就行,系统自带 Chromium 依赖。但 Jenkins 自托管的话,你得手动装 libnss3、libatk-bridge2.0-0 这些包,缺一个就跑不起来。
# Jenkins 自托管节点安装浏览器依赖(Debian/Ubuntu)
sudo apt-get update
sudo apt-get install -y \
libnss3 \
libatk-bridge2.0-0 \
libcups2 \
libdrm2 \
libxkbcommon0 \
libxcomposite1 \
libxdamage1 \
libxrandr2 \
libgbm1 \
libpango-1.0-0 \
libcairo2 \
libasound2
避坑提醒:我曾经在 Jenkins 上遇到过,跑无障碍测试时一直报 Failed to launch the browser process。查了半天,发现是少了 libgconf-2-4 这个包。建议你写一个 Dockerfile 把所有依赖打包,一劳永逸。
4.4 实战配置:GitHub Actions + axe-core
下面我给出一个最常用的配置。这个 workflow 会在每次 push 时自动跑无障碍扫描,并把结果输出成 HTML 报告。
# .github/workflows/a11y-tests.yml
name: Accessibility CI
on:
push:
branches: [ "main", "develop" ]
pull_request:
branches: [ "main" ]
jobs:
a11y-scan:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: npm ci
- name: Build project
run: npm run build
- name: Run a11y tests
run: npx axe --show-report --exit
continue-on-error: true
- name: Upload report
uses: actions/upload-artifact@v4
with:
name: a11y-report
path: ./a11y-report.html
注意看 continue-on-error: true 这个字段。我个人习惯不把无障碍测试作为“拦路虎”,而是让 CI 继续跑完,把报告归档。这样团队可以慢慢修,而不是一棍子打死。
4.5 GitLab CI 配置要点
如果你用的是 GitLab CI,流程大同小异。但有个细节值得讲:GitLab CI 喜欢用 artifacts 传递报告,而且支持 pages 功能把报告直接发布成静态站点。
# .gitlab-ci.yml
stages:
- test
- report
a11y_scan:
stage: test
image: node:20
script:
- npm ci
- npm run build
- npx axe --show-report --exit
artifacts:
paths:
- a11y-report.html
expire_in: 30 days
a11y_report:
stage: report
image: alpine:latest
script:
- cp a11y-report.html public/index.html
artifacts:
paths:
- public
only:
- main
小技巧:在 GitLab CI 里,你可以利用 rules 关键词,让无障碍扫描只在特定分支触发。比如只在 release 分支跑完整扫描,其他分支只跑 diff 扫描,能节省不少算力。
4.6 Jenkins 配置:Pipeline as Code
Jenkins 配置稍微啰嗦一点,但胜在灵活。我用的是 Declarative Pipeline 语法,好读也好维护。
// Jenkinsfile
pipeline {
agent any
tools {
nodejs 'NodeJS-20'
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Install') {
steps {
sh 'npm ci'
}
}
stage('Build') {
steps {
sh 'npm run build'
}
}
stage('A11y Test') {
steps {
sh 'npx axe --show-report --exit'
}
post {
always {
archiveArtifacts artifacts: 'a11y-report.html'
publishHTML(target: [
reportName: 'A11y Report',
reportDir: '.',
reportFiles: 'a11y-report.html',
keepAll: true
])
}
}
}
}
}
曾经踩过的坑:Jenkins 默认用户是 jenkins,权限有限。有次我跑 axe 时一直报 EACCES 错误,折腾了半天。最后发现是 node_modules 的权限问题。解决办法是在 Jenkinsfile 里加一句 sh 'npm config set cache /tmp/.npm',把缓存目录改到可写路径。
4.7 知识体系总览
我把这一整章的知识点画成了一张图。你看着这个结构,就能快速理解“为什么要选、怎么选、配置要点在哪”。
4.8 选型 checklist
最后,我留一个 checklist,你在实际选型时可以对照着看:
- 你的代码托管平台是什么?—— 优先选原生集成的
- 团队有运维能力吗?—— 没有就选 SaaS 方案
- 需要跑多少并发测试?—— Jenkins 自建节点控制力强
- 报告要展示给谁看?—— GitLab Pages 或 GitHub Pages 很方便
- 是否涉及敏感数据?—— 自托管 GitLab CI 或 Jenkins 更安全
这一套下来,CI 环境搭建应该不会有大问题了。核心就是:别贪多,把基础配置跑通,先让无障碍测试跑起来,再慢慢优化。