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 能解决三个痛点:

  1. 一致性:每次都在干净容器里跑,结果可复现
  2. 自动化:Push 代码自动触发,不用人工记着跑
  3. 拦截:无障碍问题不修,合并按钮就变灰

说白了,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 知识体系总览

我把这一整章的知识点画成了一张图。你看着这个结构,就能快速理解“为什么要选、怎么选、配置要点在哪”。

CI 环境搭建知识体系 CI 环境选择与配置 GitHub Actions GitLab CI Jenkins 特征 SaaS 零维护 / 市场丰富 与 GitHub 深度集成 特征 私有化部署 / 安全可控 Job 与 Artifacts 灵活 特征 插件生态最强 / 高度定制 维护成本高 / 学习曲线陡 无障碍测试公共需求 Docker 容器化环境 浏览器依赖安装 报告归档与发布

4.8 选型 checklist

最后,我留一个 checklist,你在实际选型时可以对照着看:

  • 你的代码托管平台是什么?—— 优先选原生集成的
  • 团队有运维能力吗?—— 没有就选 SaaS 方案
  • 需要跑多少并发测试?—— Jenkins 自建节点控制力强
  • 报告要展示给谁看?—— GitLab Pages 或 GitHub Pages 很方便
  • 是否涉及敏感数据?—— 自托管 GitLab CI 或 Jenkins 更安全

这一套下来,CI 环境搭建应该不会有大问题了。核心就是:别贪多,把基础配置跑通,先让无障碍测试跑起来,再慢慢优化。