
类型:代码托管平台
简介:只支持Git作为唯一的版本库格式进行托管,故名GitHub。
一个项目在本地 Node 20 能通过,不代表 Node 18、Node 22 或不同系统上也能正常运行。尤其是 CLI 工具、前端构建工具、跨平台脚本和开源库,用户运行环境很分散。如果每个环境都单独写一份 workflow,维护成本会很高。GitHub Actions 的 matrix 可以把版本、系统、依赖组合展开成多组任务,用一份配置覆盖多个测试场景。
一、什么时候需要矩阵构建
并不是所有仓库都需要 matrix。如果项目只部署到固定服务器,运行环境单一,普通 workflow 就够用。矩阵构建适合开源包、跨平台工具、需要支持多个语言版本的项目,或希望在升级依赖前确认兼容性的团队。
例如一个 Node 工具声明支持 Node 18、20、22,就应该至少在这三个版本上跑测试。否则 README 写的兼容范围没有验证依据。对于需要支持 Windows 的命令行工具,还应在 ubuntu、windows 之间做基本覆盖。
二、从单版本配置改成matrix
普通 Node 测试通常写一个 node-version。改成 matrix 后,可以把版本列表放进 strategy:
strategy:
matrix:
node-version: [18, 20, 22]
steps:
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
这样同一个 job 会展开成三次运行,每次使用不同 Node 版本。日志页面会显示每个组合,失败时能看到具体是哪一个版本出问题。
三、加入操作系统维度
如果还要测试系统差异,可以加入 os:
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
node-version: [18, 20, 22]
runs-on: ${{ matrix.os }}
这会生成 2×3 共 6 个任务。组合数量会快速增加,所以不要无节制地添加维度。每增加一个维度,都意味着更多运行时间和更多失败排查成本。
四、用exclude减少无意义组合
有些组合没有必要跑。比如某个旧 Node 版本只在 Linux 上做兼容验证,Windows 只跑最新 LTS。可以使用 exclude 排除:
exclude: - os: windows-latest node-version: 18
exclude 的价值是保留矩阵配置的清晰度,同时减少资源浪费。相比拆成多个 job,matrix 更容易看出测试策略。
五、fail-fast要看项目阶段
matrix 默认可能在某个组合失败后取消其他组合。对快速反馈来说,这很节省时间;但如果想一次收集所有环境的失败情况,可以设置 fail-fast: false。
开源项目做兼容性巡检时,fail-fast: false 更有价值,因为维护者能一次看到 Node 18、20、Windows、Linux 分别是否失败。日常提交检查则可以保留快速失败,先减少等待。
六、include适合补充特殊组合
include 可以给某些组合添加额外字段。例如 Node 22 使用实验性标记,或某个系统使用不同安装命令。不要把 include 写成大段复杂逻辑,否则 matrix 会变得难读。一般做法是把少量特殊项放入 include,主要组合仍保持规则化。
如果特殊情况很多,说明测试目标已经分化,可能应该拆成两个 job:一个负责常规兼容,一个负责特殊环境验证。
七、矩阵失败后怎么定位
矩阵失败时,不要只看总状态。点开失败的具体组合,看系统、语言版本和失败步骤。若只有 Windows 失败,重点查路径分隔符、shell 差异、换行符和权限;若只有旧 Node 失败,查语法、依赖最低版本和 package engines;若所有组合都失败,多半是代码或依赖安装本身有问题。
建议在测试输出里打印版本信息,例如 node -v、npm -v。这样截图或日志转发时,不用反复回到配置文件确认环境。
八、控制运行成本
矩阵构建很好用,但也容易把 CI 拖慢。小团队可以采用分层策略:PR 只跑主系统和 LTS 版本,main 分支或夜间任务再跑完整矩阵。这样既能快速给开发反馈,又能定期发现兼容性问题。
对于站长工具、主题构建、开源脚本类项目,通常先覆盖 ubuntu + 当前 LTS,再根据用户反馈增加 Windows 或更多版本。测试矩阵应随真实使用场景扩大,而不是一开始追求完整。
九、不要把矩阵当成展示配置
矩阵构建最容易写得很好看,却没有解决真实问题。比如项目只支持 Linux 部署,却同时跑三个系统;或者声明支持 Node 18,但实际依赖已经要求 Node 20。矩阵配置应服务于兼容承诺,而不是为了让 CI 页面更复杂。
在写 matrix 前,可以先列出项目必须支持的环境:生产部署用什么系统,用户本地常用什么版本,包管理器最低要求是什么。只有这些环境需要稳定验证,才值得放进矩阵。其余环境可以放到定期任务或手动 workflow 中,不必每个 PR 都跑。
十、矩阵名称要让失败一眼可读
当矩阵组合较多时,任务名称很重要。可以在 job name 中加入系统和版本,例如 `test-node-${{ matrix.node-version }}-${{ matrix.os }}`。这样 Actions 列表里不用点开详情,也能知道失败发生在哪个组合。
如果还有数据库、浏览器或依赖版本维度,也应让名称反映关键信息。CI 失败时,维护者最怕看到一串相同名字的 job,只能逐个点开。清楚的名称能节省大量排查时间。
十一、兼容失败后的处理方式
矩阵发现某个旧版本失败后,不一定只有“立刻修复”一种选择。如果该版本仍在项目承诺范围内,就应修复代码或调整依赖;如果该版本已经不再适合支持,应更新 README、package engines 和发布说明,明确最低版本要求。
开源项目尤其要避免“文档写支持,CI 已经失败”的状态。矩阵构建不仅是测试工具,也是维护兼容承诺的证据。用户看到项目持续在多个环境通过测试,会更容易判断项目是否可靠。
十二、完整矩阵可以放到定时任务
有些组合运行很慢,但又不能完全放弃。可以让 PR 跑核心矩阵,例如 ubuntu + 当前 LTS;每天或每周再跑完整矩阵,包括 Windows、旧版本和实验版本。这样日常开发不会被长时间 CI 阻塞,同时还能定期发现兼容问题。
这种分层方式适合文档站生成器、CLI 工具、主题构建脚本和开源插件。矩阵构建的目标是及时暴露风险,而不是让每次小改动都等待所有环境跑完。

