mcpField
A
actions-ci-tuning

actions-ci-tuning

github.com/mizchi云与 DevOps41645 次安装1 周前更新
代码仓库

关于 actions-ci-tuning

用于审计和改进 GitHub Actions 工作流的技能,面向维护 CI 的开发团队。它先处理正确性问题,再检查缓存、并行测试、制品保护、可靠性和安全配置,并提出最小改动。

主要功能

  1. 01盘点工作流与运行时长
  2. 02检查依赖缓存和安装方式
  3. 03审查并行任务与测试分片
  4. 04检查制品合并保护
  5. 05核查并发、触发器和版本固定

适用场景

  1. 01诊断 CI 运行失败或变慢
  2. 02优化 Playwright 测试分片与报告
  3. 03降低缓存失效和锁文件漂移风险
  4. 04审查 GitHub Actions 安全配置

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mizchi/skills --skill actions-ci-tuning

安装后在 Claude Code 中输入/actions-ci-tuning确认已加载。

附带文件README.md

详细介绍

GitHub Actions CI 调优

审查并改进 GitHub Actions 工作流。优先关注正确性(作业报错而非失败),其次是速度(缓存、并行),最后是可靠性(不稳定性、产物保护)。


工作流

  1. 盘点 — 列出所有 .github/workflows/*.yml 文件及其触发事件、作业和大致耗时(gh run list --workflow <file> --limit 5)。
  2. 根据清单审查 — 逐项检查下方各部分,并标记所有缺漏。
  3. 确定优先级 — 按影响分组:正确性缺陷 > 缓存未命中 > 并行优化 > 外观问题。
  4. 提出更改 — 起草最小差异;不要重构无关部分。
  5. 验证 — 应用更改后,通过 gh run list 确认下一次运行通过且速度更快。

检查清单

包管理器缓存

缓存未命中意味着每次运行都要重新下载数百个包。在大多数仓库中,这是投资回报率最高的单项修复。

pnpm

- uses: pnpm/action-setup@v6
  with:
    version: latest           # or pin to a specific version

- uses: actions/setup-node@v7
  with:
    node-version-file: .nvmrc  # or node-version: '24' (current LTS)
    cache: 'pnpm'              # ← must be present; omitting it silently skips caching

常见错误:调用 corepack enable 而非 pnpm/action-setup。corepack enable 不会设置 pnpm store 缓存 — actions/setup-node cache: 'pnpm' 要求先运行 pnpm/action-setup。

npm

- uses: actions/setup-node@v7
  with:
    node-version-file: .nvmrc
    cache: 'npm'

yarn(classic / berry)

- uses: actions/setup-node@v7
  with:
    node-version-file: .nvmrc
    cache: 'yarn'

验证缓存是否生效:在 setup-node 日志中查找 Cache restored successfully。如果没有,可能是缺少 cache: 键,或锁文件路径错误。


依赖安装
  • 在 CI 中始终使用 --frozen-lockfile(pnpm)/ --ci(npm)/ --immutable(yarn berry)。这样可以防止锁文件漂移导致已安装的依赖树悄然变化。
  • 在 CI 中绝不要使用不带冻结标志的 npm install 或 pnpm install。

并行作业与步骤
  • 独立作业(lint、typecheck、test)应拆分为不同作业并行运行,而不是作为顺序步骤执行。
  • 顺序步骤适合在单个作业中进行设置(安装 → 构建 → 测试)。
  • 如果仓库把 lint、typecheck 和单元测试都放在一个作业中,应将它们拆分。
jobs:
  lint:
    runs-on: ubuntu-latest
    steps: [checkout, setup, install, run lint]
  typecheck:
    runs-on: ubuntu-latest
    steps: [checkout, setup, install, run typecheck]
  test:
    runs-on: ubuntu-latest
    steps: [checkout, setup, install, run test]

测试分片(Playwright / Vitest)

使用分片缩短耗时较长的测试套件。每个分片并行运行一部分测试。

Playwright 示例 — 4 个分片:

jobs:
  e2e:
    strategy:
      fail-fast: false
      matrix:
        shard: [1, 2, 3, 4]
    steps:
      - run: pnpm exec playwright test --shard=${{ matrix.shard }}/4
        env:
          CI: true
      - uses: actions/upload-artifact@v7
        if: ${{ !cancelled() }}       # ← upload even on test failure
        with:
          name: blob-report-${{ matrix.shard }}
          path: blob-report/
          retention-days: 1

注意事项:

  • 必须设置 fail-fast: false,否则一个分片失败就会取消其余分片,导致它们无法上传 blob 报告。
  • 在上传步骤中设置 if: ${{ !cancelled() }},确保即使测试失败也会上传 blob 报告。否则,merge-reports 作业将收不到任何产物。

merge-reports 中的产物保护

如果分片可能在上传 blob 报告前失败,all-blob-reports 目录可能不存在。为合并命令添加保护:

- name: Merge reports
  run: |
    if [ -d all-blob-reports ] && [ "$(ls -A all-blob-reports 2>/dev/null)" ]; then
      pnpm exec playwright merge-reports --reporter=html ./all-blob-reports
    else
      echo "No blob reports found, skipping merge"
      mkdir -p playwright-report
      echo "<html><body><p>No test results available</p></body></html>" > playwright-report/index.html
    fi

如果没有此保护,即使整个工作流本应正常报告“无结果”,merge-reports 作业仍会报错:Error: Directory does not exist: ./all-blob-reports。


Playwright Docker 镜像

对于 VRT(视觉回归测试),快照必须在与 CI 相同的环境中生成(Linux + 指定字体)。使用官方 Playwright Docker 镜像,而非普通的 node:* 镜像:

mcr.microsoft.com/playwright:v1.59.1-noble   # pin to the same version as @playwright/test

为什么不用 node:24?

  • node:24 需要运行 playwright install --with-deps chromium,这会触发 apt-get,在 macOS 上的 Docker Desktop 中可能因已知的 QEMU 模拟环境 apt 问题而卡住数小时。
  • mcr.microsoft.com/playwright 镜像已预装 Chromium 和所有系统依赖 — 无需 apt-get,几秒内即可启动。

版本固定:确保镜像版本与 package.json 中的 @playwright/test 版本一致。版本不匹配会导致找不到浏览器的错误。


并发控制

取消同一分支/PR 上正在进行的运行,避免队列积压:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

例外:不要取消 main 上的发布/部署工作流。仅对 PR 分支启用:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}

定时工作流可靠性
  • 如果仓库 60 天内没有活动,GitHub Actions 上的定时工作流可能会悄然停止触发。
  • 在 schedule: 旁添加 workflow_dispatch: 触发器,这样无需更改代码即可手动重新触发。
  • 对于关键的定时任务(例如每晚运行的 E2E),添加失败通知步骤(创建 GitHub issue、发送 Slack 通知等),以便发现静默失败。
on:
  schedule:
    - cron: '0 0 * * *'
  workflow_dispatch:      # ← always add this

Action 版本固定
  • 将第三方 Action 固定到完整的提交 SHA,而不是标签。标签可能会被移动。
  • 使用注释注明易读的版本:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
  • Dependabot 或 Renovate 可以自动更新 SHA 固定值。检查 .github/dependabot.yml 是否包含 github-actions 生态系统。

Node.js 20 弃用警告:GitHub 于 2025/2026 年开始发出“Node.js 20 actions are deprecated”警告。这指的是 Action 自身的运行时(runs.using: node20),而不是项目的 Node 版本。请升级到首个使用 node24 的主版本:

action首个 node24 主版本当前主版本(2026-09)
actions/checkoutv6.0.0v7
actions/setup-nodev6.0.0v7
actions/cachev5.0.0v6
actions/upload-artifactv7.0.0v7
actions/download-artifactv8.0.0v8
aws-actions/configure-aws-credentialsv6.0.0v6

最新的固定 SHA(已于 2026-09 验证):

uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: aws-actions/configure-aws-credentials@cbe3b392738ccf3f987d68400dafcf4b0624a56c # v6.2.4

注意:SHA 会变动——固定之前,务必使用 gh release view --repo <owner>/<action> 进行验证。


环境变量
  • CI: true 应设置在作业或工作流级别,而不仅仅是在单独的运行步骤中。许多工具(Playwright、Vite 等)会根据此标志更改行为。
  • 密钥应使用 ${{ secrets.NAME }}——切勿硬编码令牌。
  • 对于受限运行器上的大型构建,有时需要设置 NODE_OPTIONS: --max-old-space-size=4096(7 GB 运行器的默认堆内存约为 1.5 GB)。

快速审计命令

# List recent run durations for a workflow
gh run list --workflow e2e.yml --limit 10 --json databaseId,displayTitle,createdAt,updatedAt,conclusion \
  | jq '.[] | {title: .displayTitle, duration: (.updatedAt | fromdate) - (.createdAt | fromdate), conclusion: .conclusion}'

# Find jobs that always time out
gh run list --workflow e2e.yml --status failure --limit 20 --json databaseId \
  | jq -r '.[].databaseId' \
  | xargs -I{} gh run view {} --json jobs \
  | jq '.jobs[] | select(.conclusion == "timed_out") | .name'

# Check cache usage in a run
gh run view <run_id> --log | grep -i "cache"

常见反模式

反模式问题修复方法
仅使用 corepack enable(没有 pnpm/action-setup)pnpm 存储区不会被缓存在 setup-node 之前添加 pnpm/action-setup@v6
pnpm install 未使用 --frozen-lockfile锁文件可能在不知情的情况下发生漂移在 CI 中始终使用 --frozen-lockfile
测试矩阵中设置 fail-fast: true分片会在上传制品前取消设置 fail-fast: false
上传制品时未使用 if: ${{ !cancelled() }}测试失败时 Blob 报告会丢失添加 if 条件
使用 playwright merge-reports 时未检查目录没有分片上传时作业会报错使用 [ -d all-blob-reports ] 检查进行保护
Playwright VRT 使用 node:* 镜像在 macOS 上,Docker Desktop 中的 apt-get 会卡住使用 mcr.microsoft.com/playwright 镜像
定时工作流未配置 workflow_dispatch无法手动重新触发始终添加 workflow_dispatch:
Action 固定到标签而非 SHA标签可能会被移动(供应链风险)固定到完整的提交 SHA

评论

支持 Markdown