matrix-optimizer
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMatrix Optimizer
矩阵优化器
Configure and optimize GitHub Actions matrix strategies for efficient multi-version and multi-platform testing.
配置并优化GitHub Actions矩阵策略,以实现高效的多版本和多平台测试。
Quick Start
快速开始
Basic matrix for testing multiple Node.js versions:
yaml
strategy:
matrix:
node-version: [16, 18, 20]用于测试多个Node.js版本的基础矩阵:
yaml
strategy:
matrix:
node-version: [16, 18, 20]Instructions
操作指南
Step 1: Identify Matrix Dimensions
步骤1:确定矩阵维度
Common matrix dimensions:
- Language versions: Node.js, Python, Ruby, Go versions
- Operating systems: ubuntu, macos, windows
- Architectures: x64, arm64
- Dependency versions: Database versions, framework versions
- Feature flags: Different configuration options
Example dimensions:
yaml
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node-version: [16, 18, 20]
# This creates 9 jobs (3 OS × 3 versions)常见矩阵维度:
- 语言版本:Node.js、Python、Ruby、Go版本
- 操作系统:ubuntu、macos、windows
- 架构:x64、arm64
- 依赖版本:数据库版本、框架版本
- 功能标志:不同配置选项
示例维度:
yaml
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node-version: [16, 18, 20]
# 这会创建9个任务(3个操作系统 × 3个版本)Step 2: Configure Matrix Strategy
步骤2:配置矩阵策略
Basic matrix:
yaml
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
node-version: [18, 20]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: npm testMatrix with include:
yaml
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
node-version: [18, 20]
include:
# Add specific combination
- os: windows-latest
node-version: 20
# Add extra variables for specific combination
- os: ubuntu-latest
node-version: 20
experimental: trueMatrix with exclude:
yaml
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node-version: [16, 18, 20]
exclude:
# Skip Node 16 on Windows
- os: windows-latest
node-version: 16
# Skip Node 16 on macOS
- os: macos-latest
node-version: 16基础矩阵:
yaml
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
node-version: [18, 20]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: npm test包含额外配置的矩阵:
yaml
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
node-version: [18, 20]
include:
# 添加特定组合
- os: windows-latest
node-version: 20
# 为特定组合添加额外变量
- os: ubuntu-latest
node-version: 20
experimental: true排除指定组合的矩阵:
yaml
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node-version: [16, 18, 20]
exclude:
# 跳过Windows上的Node 16
- os: windows-latest
node-version: 16
# 跳过macOS上的Node 16
- os: macos-latest
node-version: 16Step 3: Optimize for Cost and Speed
步骤3:针对成本与速度进行优化
Fail-fast strategy:
yaml
strategy:
fail-fast: false # Continue all jobs even if one fails
matrix:
node-version: [16, 18, 20]Max parallel jobs:
yaml
strategy:
max-parallel: 2 # Limit concurrent jobs
matrix:
node-version: [16, 18, 20]Conditional matrix:
yaml
strategy:
matrix:
os: [ubuntu-latest]
# Add more OS only on main branch
${{ github.ref == 'refs/heads/main' && fromJSON('["macos-latest", "windows-latest"]') || fromJSON('[]') }}失败不终止策略:
yaml
strategy:
fail-fast: false # 即使有任务失败,仍继续执行所有任务
matrix:
node-version: [16, 18, 20]最大并行任务数:
yaml
strategy:
max-parallel: 2 # 限制并发任务数
matrix:
node-version: [16, 18, 20]条件化矩阵:
yaml
strategy:
matrix:
os: [ubuntu-latest]
# 仅在主分支添加更多操作系统
${{ github.ref == 'refs/heads/main' && fromJSON('["macos-latest", "windows-latest"]') || fromJSON('[]') }}Step 4: Use Matrix Variables
步骤4:使用矩阵变量
In job steps:
yaml
steps:
- name: Display matrix values
run: |
echo "OS: ${{ matrix.os }}"
echo "Version: ${{ matrix.node-version }}"
echo "Experimental: ${{ matrix.experimental }}"In job configuration:
yaml
jobs:
test:
runs-on: ${{ matrix.os }}
continue-on-error: ${{ matrix.experimental == true }}
strategy:
matrix:
os: [ubuntu-latest]
node-version: [18, 20]
include:
- node-version: 21
experimental: true在任务步骤中使用:
yaml
steps:
- name: Display matrix values
run: |
echo "OS: ${{ matrix.os }}"
echo "Version: ${{ matrix.node-version }}"
echo "Experimental: ${{ matrix.experimental }}"在任务配置中使用:
yaml
jobs:
test:
runs-on: ${{ matrix.os }}
continue-on-error: ${{ matrix.experimental == true }}
strategy:
matrix:
os: [ubuntu-latest]
node-version: [18, 20]
include:
- node-version: 21
experimental: trueStep 5: Name Jobs Clearly
步骤5:清晰命名任务
yaml
jobs:
test:
name: Test on ${{ matrix.os }} with Node ${{ matrix.node-version }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
node-version: [18, 20]yaml
jobs:
test:
name: Test on ${{ matrix.os }} with Node ${{ matrix.node-version }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
node-version: [18, 20]Common Patterns
常见模式
Language Version Matrix
语言版本矩阵
Node.js:
yaml
strategy:
matrix:
node-version: [16, 18, 20]
steps:
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}Python:
yaml
strategy:
matrix:
python-version: ['3.9', '3.10', '3.11', '3.12']
steps:
- uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}Go:
yaml
strategy:
matrix:
go-version: ['1.20', '1.21', '1.22']
steps:
- uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go-version }}Node.js:
yaml
strategy:
matrix:
node-version: [16, 18, 20]
steps:
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}Python:
yaml
strategy:
matrix:
python-version: ['3.9', '3.10', '3.11', '3.12']
steps:
- uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}Go:
yaml
strategy:
matrix:
go-version: ['1.20', '1.21', '1.22']
steps:
- uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go-version }}Cross-Platform Matrix
跨平台矩阵
yaml
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
include:
# Platform-specific configurations
- os: ubuntu-latest
install-cmd: sudo apt-get install
- os: macos-latest
install-cmd: brew install
- os: windows-latest
install-cmd: choco install
steps:
- name: Install dependencies
run: ${{ matrix.install-cmd }} package-nameyaml
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
include:
# 平台特定配置
- os: ubuntu-latest
install-cmd: sudo apt-get install
- os: macos-latest
install-cmd: brew install
- os: windows-latest
install-cmd: choco install
steps:
- name: Install dependencies
run: ${{ matrix.install-cmd }} package-nameDatabase Version Matrix
数据库版本矩阵
yaml
strategy:
matrix:
postgres-version: [12, 13, 14, 15]
services:
postgres:
image: postgres:${{ matrix.postgres-version }}
env:
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5yaml
strategy:
matrix:
postgres-version: [12, 13, 14, 15]
services:
postgres:
image: postgres:${{ matrix.postgres-version }}
env:
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5Feature Flag Matrix
功能标志矩阵
yaml
strategy:
matrix:
feature:
- name: baseline
flags: ''
- name: new-parser
flags: '--enable-new-parser'
- name: experimental
flags: '--enable-experimental'
steps:
- name: Run tests
run: npm test ${{ matrix.feature.flags }}yaml
strategy:
matrix:
feature:
- name: baseline
flags: ''
- name: new-parser
flags: '--enable-new-parser'
- name: experimental
flags: '--enable-experimental'
steps:
- name: Run tests
run: npm test ${{ matrix.feature.flags }}Optimization Strategies
优化策略
Reduce Matrix Size
缩小矩阵规模
Before (12 jobs):
yaml
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node-version: [16, 18, 20, 21]After (7 jobs):
yaml
matrix:
# Test all versions on Linux only
os: [ubuntu-latest]
node-version: [16, 18, 20, 21]
include:
# Test latest version on other platforms
- os: macos-latest
node-version: 21
- os: windows-latest
node-version: 21优化前(12个任务):
yaml
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node-version: [16, 18, 20, 21]优化后(7个任务):
yaml
matrix:
# 仅在Linux上测试所有版本
os: [ubuntu-latest]
node-version: [16, 18, 20, 21]
include:
# 在其他平台上仅测试最新版本
- os: macos-latest
node-version: 21
- os: windows-latest
node-version: 21Conditional Matrix Expansion
条件化矩阵扩展
yaml
strategy:
matrix:
# Always test on Linux
os: [ubuntu-latest]
node-version: [18, 20]
include:
# Full matrix only on main branch or release tags
- ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') }}:
os: [macos-latest, windows-latest]yaml
strategy:
matrix:
# 始终在Linux上测试
os: [ubuntu-latest]
node-version: [18, 20]
include:
# 仅在主分支或发布标签下使用完整矩阵
- ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') }}:
os: [macos-latest, windows-latest]Parallel vs Sequential
并行与串行对比
High parallelism (faster, more expensive):
yaml
strategy:
matrix:
shard: [1, 2, 3, 4, 5, 6, 7, 8]
steps:
- run: npm test -- --shard=${{ matrix.shard }}/8Limited parallelism (slower, cheaper):
yaml
strategy:
max-parallel: 2
matrix:
shard: [1, 2, 3, 4, 5, 6, 7, 8]高并行度(更快,成本更高):
yaml
strategy:
matrix:
shard: [1, 2, 3, 4, 5, 6, 7, 8]
steps:
- run: npm test -- --shard=${{ matrix.shard }}/8有限并行度(更慢,成本更低):
yaml
strategy:
max-parallel: 2
matrix:
shard: [1, 2, 3, 4, 5, 6, 7, 8]Caching Across Matrix
跨矩阵缓存
yaml
steps:
- uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ matrix.node-version }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-${{ matrix.node-version }}-
${{ runner.os }}-node-yaml
steps:
- uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ matrix.node-version }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-${{ matrix.node-version }}-
${{ runner.os }}-node-Advanced Patterns
高级模式
Dynamic Matrix from JSON
从JSON生成动态矩阵
yaml
jobs:
setup:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- id: set-matrix
run: |
# Generate matrix dynamically
MATRIX='{"include":[{"os":"ubuntu-latest","version":"18"},{"os":"macos-latest","version":"20"}]}'
echo "matrix=$MATRIX" >> $GITHUB_OUTPUT
test:
needs: setup
strategy:
matrix: ${{ fromJSON(needs.setup.outputs.matrix) }}
runs-on: ${{ matrix.os }}
steps:
- run: echo "Testing on ${{ matrix.os }} with version ${{ matrix.version }}"yaml
jobs:
setup:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- id: set-matrix
run: |
# 动态生成矩阵
MATRIX='{"include":[{"os":"ubuntu-latest","version":"18"},{"os":"macos-latest","version":"20"}]}'
echo "matrix=$MATRIX" >> $GITHUB_OUTPUT
test:
needs: setup
strategy:
matrix: ${{ fromJSON(needs.setup.outputs.matrix) }}
runs-on: ${{ matrix.os }}
steps:
- run: echo "Testing on ${{ matrix.os }} with version ${{ matrix.version }}"Matrix with Outputs
带输出的矩阵
yaml
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
outputs:
result-${{ matrix.os }}: ${{ steps.test.outputs.result }}
steps:
- id: test
run: echo "result=passed" >> $GITHUB_OUTPUTyaml
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
outputs:
result-${{ matrix.os }}: ${{ steps.test.outputs.result }}
steps:
- id: test
run: echo "result=passed" >> $GITHUB_OUTPUTReusable Matrix Workflow
可复用矩阵工作流
yaml
undefinedyaml
undefined.github/workflows/reusable-matrix.yml
.github/workflows/reusable-matrix.yml
on:
workflow_call:
inputs:
versions:
required: true
type: string
jobs:
test:
strategy:
matrix:
version: ${{ fromJSON(inputs.versions) }}
runs-on: ubuntu-latest
steps:
- run: echo "Testing version ${{ matrix.version }}"
on:
workflow_call:
inputs:
versions:
required: true
type: string
jobs:
test:
strategy:
matrix:
version: ${{ fromJSON(inputs.versions) }}
runs-on: ubuntu-latest
steps:
- run: echo "Testing version ${{ matrix.version }}"
Caller workflow
调用方工作流
jobs:
test:
uses: ./.github/workflows/reusable-matrix.yml
with:
versions: '["18", "20", "21"]'
undefinedjobs:
test:
uses: ./.github/workflows/reusable-matrix.yml
with:
versions: '["18", "20", "21"]'
undefinedTroubleshooting
故障排除
Too many jobs:
- Use to remove unnecessary combinations
exclude - Test all versions on one OS, latest version on others
- Use conditional matrix expansion for PRs vs main
Jobs failing inconsistently:
- Set to see all failures
fail-fast: false - Check for race conditions or timing issues
- Verify platform-specific dependencies
Slow matrix execution:
- Increase if budget allows
max-parallel - Optimize caching strategy
- Consider test sharding within jobs
Matrix not expanding:
- Verify JSON syntax in
fromJSON() - Check that matrix variables are properly referenced
- Ensure and
includesyntax is correctexclude
任务数量过多:
- 使用移除不必要的组合
exclude - 在一个操作系统上测试所有版本,在其他操作系统上仅测试最新版本
- 针对PR和主分支使用不同的条件化矩阵扩展
任务失败情况不一致:
- 设置以查看所有失败情况
fail-fast: false - 检查竞争条件或时序问题
- 验证平台特定依赖
矩阵执行缓慢:
- 如果预算允许,增加值
max-parallel - 优化缓存策略
- 考虑在任务内进行测试分片
矩阵未展开:
- 验证中的JSON语法
fromJSON() - 检查矩阵变量是否被正确引用
- 确保和
include语法正确exclude
Best Practices
最佳实践
- Start small: Begin with minimal matrix, expand as needed
- Test locally first: Verify one configuration works before expanding
- Use fail-fast: false: See all failures, not just first
- Name jobs clearly: Include matrix values in job names
- Cache effectively: Use matrix values in cache keys
- Optimize for PRs: Smaller matrix for PRs, full matrix for main
- Document matrix: Explain why each dimension is needed
- Monitor costs: Track runner minutes usage
- 从小规模开始:先使用最小矩阵,再根据需要扩展
- 先本地测试:在扩展前先验证单个配置可正常工作
- 使用fail-fast: false:查看所有失败情况,而非仅第一个
- 清晰命名任务:在任务名称中包含矩阵值
- 有效缓存:在缓存键中使用矩阵值
- 针对PR优化:PR使用较小矩阵,主分支使用完整矩阵
- 文档化矩阵:说明每个维度的必要性
- 监控成本:跟踪运行器分钟数使用情况