mcpField
M
mergify-ci

mergify-ci

github.com/mergifyio测试与质量3270 次安装1 天前更新
代码仓库

关于 mergify-ci

mergify-ci 是面向 CI 流水线的命令行技能,可处理 JUnit 测试结果、识别受变更影响的范围,并读取拉取请求或合并队列元数据。它还提供测试健康状态查询和隔离测试管理命令。

主要功能

  1. 01处理并上传 JUnit 结果
  2. 02检测拉取请求的 Git 引用
  3. 03识别文件变更影响的范围
  4. 04发送拉取请求范围报告
  5. 05读取合并队列批次元数据
  6. 06查看测试健康状态并管理隔离

适用场景

  1. 01上传 CI 测试报告并评估隔离失败项
  2. 02仅运行受代码变更影响范围的测试
  3. 03为受影响项目命令传递拉取请求引用
  4. 04检查失败测试并更新隔离状态

安装

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

$npx skills add https://github.com/mergifyio/mergify-cli --skill mergify-ci

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

详细介绍

Mergify CI 命令

概述

mergify ci 命令组为 CI 流水线提供工具:将 JUnit 测试结果上传到 Mergify Test Engine,检测用于基于差异的操作的 git 引用,管理用于选择性测试的 CI 范围,以及获取合并队列批次元数据。

命令

mergify ci junit-process FILES...         # Upload JUnit XML + evaluate quarantine (primary command)
mergify ci junit-upload FILES...          # (Deprecated) Use junit-process instead
mergify ci git-refs                       # Detect base/head git references for the current PR
mergify ci scopes --config PATH           # Detect scopes impacted by changed files
mergify ci scopes-send -s SCOPE           # Report scopes against the pull request's head commit
mergify ci queue-info                     # Output the current build's merge queue batch metadata (from the git note)
mergify tests show NAME...                # Look up tests by name and print health, ratios, last failure
mergify tests quarantines add NAME        # Add a test to the Test Engine quarantine
mergify tests quarantines remove NAME     # Remove a test from the Test Engine quarantine
mergify tests quarantines get NAME        # Print a single quarantine by test name or id
mergify tests quarantines list            # List the tests currently in the Test Engine quarantine

身份验证

Mergify 应用密钥分为两类,均在控制面板中创建。每类密钥都只能访问各自的一组端点,而不是另一类密钥端点的子集:在此 CLI 调用的端点中,两类密钥仅共用隔离列表。

密钥可访问的端点
ciCI 作业执行的操作:跟踪上传、scopes-send、隔离评估(junit-process)以及隔离列表。
admin读取测试健康状况、隔离列表,以及修改隔离项。不能上传跟踪,也不能执行 scopes-send。

跟踪上传和 scopes-send 只能使用 ci 密钥:使用 admin 密钥或 GitHub PAT 会收到 403。下文所有拒绝 ci 密钥的其他端点均可改用 GitHub PAT。GitHub Actions 中的 GITHUB_TOKEN 不是 PAT——它是临时安装令牌——因此不要试图用它来消除这些 403 错误。

这种划分依据的是各命令调用的端点:读取测试健康状况和修改隔离项属于检查或覆盖仓库设置的人员操作,而非流水线操作,因此不在 ci 密钥的权限范围内;跟踪上传和范围报告是流水线发送的内容,因此不在 admin 密钥的权限范围内。各命令的权限如下:

命令ci 密钥admin 密钥
ci junit-process、ci junit-upload是仅可进行隔离评估——上传会收到 403,并报告为上传被拒绝(不影响退出代码)
ci scopes-send是否——403
tests quarantines list、tests quarantines get是——两者都会读取隔离列表是
tests show否——403是
tests quarantines add、tests quarantines remove否——403是

ci git-refs、ci scopes 和 ci queue-info 均在本地执行,无需令牌。

JUnit 处理(junit-process)

主要的 CI 命令。解析 JUnit XML 报告,检查失败测试的隔离状态,将结果上传到 Mergify Test Engine,并确定最终的 CI 退出代码。

mergify ci junit-process \
  --token "$MERGIFY_TOKEN" \
  --repository owner/repo \
  --tests-target-branch main \
  path/to/junit-results.xml

FILES 可以是单个路径,也可以是带引号的 glob 模式(例如,'reports/**/*.xml')。务必给模式加上引号,以便由 Mergify 而非 shell 展开;对于大型、分片的测试套件,这是推荐做法。

主要选项:

  • --token / -t(环境变量:MERGIFY_TOKEN)——CI Insights 应用密钥
  • --repository / -r——仓库全名(自动从 CI 提供商获取,其次从 git 远程仓库获取)
  • --tests-target-branch / -b——用于评估隔离状态的分支。按 CI 提供商自动检测:GitHub Actions(GITHUB_BASE_REF → GITHUB_HEAD_REF → GITHUB_REF_NAME)、Buildkite(BUILDKITE_PULL_REQUEST_BASE_BRANCH → BUILDKITE_BRANCH)、CircleCI(CIRCLE_BRANCH)、Jenkins(CHANGE_TARGET → GIT_BRANCH),然后使用当前检出的分支。若未检测到分支,本次运行将关闭隔离功能:结果仍会上传,且每项失败都会阻止 CI。
  • --api-url / -u(环境变量:MERGIFY_API_URL)——Mergify API URL(默认值:https://api.mergify.com)
  • --test-framework——测试框架名称(可选元数据)
  • --test-language——测试语言(可选元数据)
  • --test-exit-code / -e(环境变量:MERGIFY_TEST_EXIT_CODE)——测试运行器的退出代码,用于检测静默失败:运行器崩溃,但 JUnit 报告看起来正常
  • MERGIFY_TRACEPARENT(仅限环境变量)——一个 W3C traceparent,用于将上传的测试会话置于调用方已启动的跟踪中;格式错误的值会被忽略,会话将启动自己的跟踪

行为:

  1. 将 JUnit XML 文件解析为测试 span
  2. 针对 Mergify API 检查失败测试的隔离状态
  3. 根据 Mergify 发布的可接收数据 schema 检查这些 span(https://docs.mergify.com/mergify-ci-traces-schema.json),然后将其上传到 Mergify Test Engine。Mergify 会丢弃的上传内容(例如缺少分支 vcs.ref.head.name 的内容)不会发送:报告会列出缺失项,并将本次运行报告为上传被拒绝。若无法获取 schema,则会未经检查直接上传这些 span
  4. 打印摘要:运行的测试数、失败数、已隔离与阻止 CI 的失败数
  5. 如果所有失败都已隔离,则以代码 0 退出;如果有任何失败会阻止 CI,则以代码 1 退出
  6. 如果 --test-exit-code 非零,但未发现测试失败,则以代码 1 退出(静默失败检测)
  7. 上传失败不会影响退出代码(Mergify 端的问题不应导致 CI 失败),但会予以提示:在 GitHub Actions 上,如果上传被拒绝(被 schema 检查拒绝,或遇到 HTTP 4xx,但 408/429 除外,例如令牌无权访问 CI Insights),命令会发出 ::error:: 注解;对于暂时性错误(5xx、408、429、网络错误),则会发出 ::warning:: 注解;此外,还会将 test_results_upload=success|rejected|failed 写入 $GITHUB_OUTPUT,以便工作流以编程方式检测数据未被接收的情况

GitHub Actions 示例:

- name: Run tests
  id: tests
  run: pytest --junitxml=results.xml || echo "exit_code=$?" >> "$GITHUB_OUTPUT"

- name: Process test results
  if: always()
  run: |
    mergify ci junit-process \
      --test-exit-code ${{ steps.tests.outputs.exit_code || 0 }} \
      results.xml
  env:
    MERGIFY_TOKEN: ${{ secrets.MERGIFY_TOKEN }}

Git 引用(git-refs)

检测当前拉取请求上下文的基础和头部 Git 引用。在 GitHub Actions 中运行时,将结果写入 GITHUB_OUTPUT;在 Buildkite 中运行时,将结果写入 Buildkite 元数据(mergify-ci.base、mergify-ci.head、mergify-ci.source)。

mergify ci git-refs
# Output:
# Base: abc1234
# Head: def5678

输出格式(--format):

  • text(默认)——以便于阅读的 Base: / Head: 行输出
  • shell ——输出适用于 eval 的 MERGIFY_GIT_REFS_{BASE,HEAD,SOURCE}=... 行,并使用 POSIX 安全的 Shell 引用方式。无法检测基础引用时,MERGIFY_GIT_REFS_BASE=''。
  • json ——输出包含 base、head、source 键的单行 JSON 对象。无法检测基础引用时(例如 workflow_dispatch 事件),base 可能为 null;使用 jq -r '.base // ""' 将其转换为空字符串。
# Consume values in a shell script without parsing:
eval "$(mergify ci git-refs --format=shell)"
nx show projects --affected \
  --base="$MERGIFY_GIT_REFS_BASE" \
  --head="$MERGIFY_GIT_REFS_HEAD"

# Or with jq:
BASE=$(mergify ci git-refs --format=json | jq -r '.base // ""')

检测来源(按优先级排列):合并队列上下文、GitHub 拉取请求事件、GitHub 推送事件、回退到最近一次提交。

合并队列上下文是 Mergify 在合并队列分支头部写入的 Git note(refs/notes/mergify/<branch>)。在拉取请求构建、该分支的 GitHub push 构建以及该分支的 Buildkite 构建中都会读取它,因此,由没有草稿拉取请求的 push 触发器构建的合并队列批次也能获取该批次的检查基础引用。创建分支的推送没有前一个提交,因此其基础引用为默认分支。

范围(scopes)

根据 Mergify 配置文件检测受更改文件影响的 CI 范围。用于选择性/定向 CI——仅运行包含更改文件的范围所对应的测试。

# Detect scopes from changed files
mergify ci scopes --config .mergify.yml

# Detect scopes with explicit base/head
mergify ci scopes --config .mergify.yml --base origin/main --head HEAD

# Write detected scopes to a file
mergify ci scopes --config .mergify.yml --write scopes.json

主要选项:

  • --config(环境变量:MERGIFY_CONFIG_PATH)——Mergify YAML 配置文件的路径(自动检测)
  • --base ——基础 Git 引用(自动检测)
  • --head ——头部 Git 引用(默认值:HEAD)
  • --write / -w ——将检测到的范围写入 JSON 文件

配置文件通过文件模式定义范围。比较基础引用与头部引用之间的文件更改后,会识别匹配的范围,并将其作为范围名称到 "true"/"false" 的 JSON 映射写入 GITHUB_OUTPUT(在 GitHub Actions 中)或 Buildkite 元数据中的 mergify-ci.scopes(在 Buildkite 中)。

在合并队列批次构建中(草稿拉取请求,或对合并队列分支进行的 push 构建),不会根据更改文件计算范围:该命令会读取引擎为该批次写入的 Git note,并返回合并队列判定的范围(该批次的范围以及其中每个拉取请求的范围,包括拉取请求 CI 报告的范围),再加上合并队列范围。若 note 将批次标记为屏障(all_scopes: true),则会选中所有范围。这也适用于 manual 范围来源。没有 note,或 note 中没有 scopes 列表时,则会回退到比较文件差异。

重命名的文件会同时计入两个路径,与引擎的行为一致:git mv critical/guard.txt ignored/guard.txt 会影响 critical 和 ignored。

Scopes Send (scopes-send)

向 Mergify API 发送与拉取请求关联的作用域。适用于手动确定作用域,或从文件读取作用域,而非自动检测的情况。

报告以拉取请求的 head SHA 为准,因此会注明计算结果所对应的版本;较旧 head 的计算结果不能用于当前版本。head 会从 CI 环境中检测(GitHub Actions 事件负载或 BUILDKITE_COMMIT);也可以传入 --head-sha 明确指定。如果无法解析出 head SHA,或者 Mergify 部署版本早于提交端点,此命令会回退到仅根据拉取请求编号报告,这也是它过去一直采用的方式。

需要 ci 密钥——使用 admin 密钥或 GitHub PAT 会收到 403。请参阅 身份验证。

# Send specific scopes
mergify ci scopes-send -s frontend -s backend -p 123

# Send scopes from a JSON file (produced by `mergify ci scopes --write`)
mergify ci scopes-send --scopes-json scopes.json -p 123

# Send scopes from a plain-text file (one scope per line)
mergify ci scopes-send --scopes-file scopes.txt -p 123

# Declare the PR impacts every scope (merge-queue barrier),
# e.g. a build-system or CI-workflow change
mergify ci scopes-send -s build-system --all -p 123

# Name the revision explicitly (the pull request head, not the
# revision a `pull_request` job checked out)
mergify ci scopes-send -s frontend -p 123 --head-sha "$PR_HEAD_SHA"

主要选项:

  • --token / -t(环境变量:MERGIFY_TOKEN)——Mergify ci 应用密钥
  • --repository / -r ——仓库全名(自动检测)
  • --pull-request / -p ——拉取请求编号(在 GitHub Actions 中自动检测)
  • --scope / -s ——作用域名称(可重复指定)
  • --scopes-json ——包含作用域的 JSON 文件(mergify ci scopes --write 的输出)
  • --scopes-file ——纯文本文件,每行一个作用域
  • --head-sha ——计算作用域所依据的 head SHA,包含 40 个十六进制字符(从 CI 环境中自动检测)
  • --all ——声明该拉取请求会影响所有作用域。合并队列会将其视为屏障:绝不与其他拉取请求一起批处理或并行运行。具体作用域仍会随此标记一同发送。

Tests Show (tests show)

按名称在仓库的默认分支上查找测试,并显示其健康状况、成功/失败比例以及最近一次失败的上下文。此搜索使用批量 API:传入一个或多个名称(支持 glob),每个匹配项都会显示为一个区块。此命令为只读;显示匹配项后即以 0 退出,不受健康状况影响。请通过读取 --json 来根据健康状况设置门禁,而非依赖退出代码。

需要 admin 密钥或 GitHub PAT——使用 ci 密钥会收到 403。请参阅 身份验证。

# Single test.
mergify tests show -r owner/repo \
  'ApplicationKeys.spec.ts.Permissions › Should not see keys table if not admin'

# Batch with glob, narrowed to one pipeline, JSON for jq.
mergify tests show -r owner/repo \
  --pipeline-name e2e --json \
  '*test_login*' '*test_logout*' \
  | jq '.tests[] | {test_name, health_status}'

主要选项:

  • --repository / -r ——仓库全名(owner/repo);未指定时,从 CI 环境或本地 git 远程自动检测。
  • --token / -t(环境变量:MERGIFY_TOKEN)——Mergify 凭据。若没有,则使用 mergify auth login 保存的凭据;之后回退到 GITHUB_TOKEN / gh auth token,但这两者已不再用于 Mergify API。
  • --api-url / -u(环境变量:MERGIFY_API_URL)——API 基础 URL。
  • --pipeline-name、--pipeline-name-exclude ——按流水线筛选/排除。
  • --job-name、--job-name-exclude ——按作业筛选/排除。
  • --per-page ——限制搜索结果数量(1–100,服务器默认值为 10)。
  • --json ——向 stdout 输出单个 JSON 文档 {"tests": [...]}。

退出代码:

  • 0 ——已显示测试,或完全没有匹配项。健康状况不会影响此代码。
  • 6 ——Mergify API 错误,包括 ci 密钥在此处收到的 403。

添加测试隔离项(tests quarantines add)

将测试添加到仓库的 Test Engine 隔离区,使其失败不再影响 CI 判定。接受一个完全限定的测试名称;必须提供 --reason。

需要 admin 密钥或 GitHub PAT;ci 密钥会返回 403。请参阅身份验证。

# Quarantine on all branches.
mergify tests quarantines add -r owner/repo \
  --reason 'flaky — tracked in MRGFY-1234' \
  'test_login'

# Scope the quarantine to one branch (or branch pattern), JSON output.
mergify tests quarantines add -r owner/repo \
  --reason 'broken on release branch' --branch 'release/*' --json \
  'test_logout'

主要选项:

  • --repository / -r -- 仓库全名(owner/repo);未指定时,会从 CI 环境或本地 git 远程仓库自动检测。
  • --reason -- 记录为隔离原因的说明;必填。
  • --branch / -b -- 要限定的分支名称或模式。省略则适用于所有分支。
  • --token / -t(环境变量:MERGIFY_TOKEN)-- Mergify 凭据。若未提供,则使用 mergify auth login 存储的凭据;再回退到 GITHUB_TOKEN / gh auth token,但这两种方式已不再建议用于 Mergify API。
  • --api-url / -u(环境变量:MERGIFY_API_URL)-- API 基础 URL。
  • --json -- 将 {"id", "test_name", "reason", "branch"} 输出到 stdout。

退出代码:

  • 0 -- 测试已隔离。
  • 6 -- Mergify API 错误(例如,测试已处于隔离状态)。

移除测试隔离项(tests quarantines remove)

从隔离区移除测试。接受完全限定的测试名称(通过列表端点解析为其隔离项 ID),或直接接受隔离项 ID(由 tests quarantines add 输出)。形似 UUID 的参数会被视为 ID,并直接删除,不进行查找。

需要 admin 密钥或 GitHub PAT;ci 密钥会返回 403。请参阅身份验证。

# By test name.
mergify tests quarantines remove -r owner/repo 'test_login'

# By quarantine id (the value `tests quarantines add` printed).
mergify tests quarantines remove -r owner/repo 12345678-1234-5678-1234-567812345678

主要选项:

  • --repository / -r -- 仓库全名(owner/repo);未指定时,会从 CI 环境或本地 git 远程仓库自动检测。
  • --token / -t(环境变量:MERGIFY_TOKEN)-- Mergify 凭据。若未提供,则使用 mergify auth login 存储的凭据;再回退到 GITHUB_TOKEN / gh auth token,但这两种方式已不再建议用于 Mergify API。
  • --api-url / -u(环境变量:MERGIFY_API_URL)-- API 基础 URL。
  • --json -- 将 {"id", "test_name"} 输出到 stdout(通过 ID 指定时,test_name 为 null)。

退出代码:

  • 0 -- 测试已取消隔离。
  • 6 -- Mergify API 错误(例如,测试不在隔离区中)。

获取测试隔离项(tests quarantines get)

按完全限定的测试名称或隔离项 ID(形似 UUID 的参数会与 ID 匹配)打印单个隔离项。输出格式与 tests quarantines list 中的一条记录一致。

# By test name.
mergify tests quarantines get -r owner/repo 'test_login'

# By quarantine id, JSON output.
mergify tests quarantines get -r owner/repo --json \
  12345678-1234-5678-1234-567812345678

主要选项:

  • --repository / -r -- 仓库全名(owner/repo);未指定时,会从 CI 环境或本地 git 远程仓库自动检测。
  • --token / -t(环境变量:MERGIFY_TOKEN)-- Mergify 凭据。若未提供,则使用 mergify auth login 存储的凭据;再回退到 GITHUB_TOKEN / gh auth token,但这两种方式已不再建议用于 Mergify API。
  • --api-url / -u(环境变量:MERGIFY_API_URL)-- API 基础 URL。
  • --json -- 将记录(id、test_name、reason、branch、created_at、source、is_recovered)输出到 stdout。

退出代码:

  • 0 -- 已找到并打印隔离项。
  • 6 -- Mergify API 错误(例如,没有匹配的隔离项)。

测试隔离列表(tests quarantines list)

列出当前处于仓库 Test Engine 隔离区的所有测试。无需指定测试参数——命令会打印整个隔离区。人类可读输出中,每条记录占一个缩进块——测试名称单独占一行(绝不会在名称中间换行),随后依次显示其 ID(delete 接受的值)、分支、来源、恢复状态和原因。--json 会输出完整记录。

# Human output (one block per record).
mergify tests quarantines list -r owner/repo

# JSON for jq -- e.g. names of quarantines an auto-recover run flagged.
mergify tests quarantines list -r owner/repo --json \
  | jq -r '.quarantined_tests[] | select(.is_recovered) | .test_name'

branch 为 null 时显示为 *(表示隔离适用于所有分支)。 source 为 manual(由用户添加)或 auto(由不稳定测试检测添加)。 is_recovered 用于标记近期运行结果表明可以移除的隔离项。

主要选项:

  • --repository / -r —— 仓库全名(owner/repo);如果未指定,则从 CI 环境或本地 git 远程自动检测。
  • --token / -t(环境变量:MERGIFY_TOKEN)—— Mergify 凭据。若未提供,则使用 mergify auth login 保存的凭据;再否则使用 GITHUB_TOKEN / gh auth token,这两种方式对 Mergify API 而言均已弃用。
  • --api-url / -u(环境变量:MERGIFY_API_URL)—— API 基础 URL。
  • --json —— 向 stdout 输出 {"quarantined_tests": [...]},每条记录包含 id、test_name、reason、branch、created_at、source、is_recovered。

退出代码:

  • 0 —— 始终返回,包括隔离区为空的情况(“未找到隔离测试。”)。

队列信息(queue-info)

将当前构建的合并队列批次元数据以 JSON 格式输出。读取 Mergify 写入当前 HEAD 所在合并队列分支头部的 git note refs/notes/mergify/<branch>;找不到 note 时(即当前构建不是合并队列批次构建)会以 INVALID_STATE(7)退出。无需参数,也不需要 GitHub 令牌。

note 的完整载荷会原样输出(包括 Mergify 写入的每个字段,例如 checking_base_sha、包含各 PR 的 scopes 的 pull_requests、previous_failed_batches 和顶层的 scopes)。新字段会自动出现,无需更新 CLI,因此不要假设架构固定不变。

# In CI, on a merge queue batch build. Works in any CI (GitHub Actions,
# GitLab, CircleCI, Jenkins, ...) with plain git. When GITHUB_OUTPUT is
# set (GitHub Actions runner) it also writes the metadata there.
mergify ci queue-info

Mergify 会将批次元数据作为 git note 附加到 MQ 分支头部提交,因此读取它只需要 git,不需要 PR 正文或 GitHub 令牌。命令会自行运行 git fetch origin "refs/notes/mergify/*"(默认不会获取 notes),然后返回附加到 HEAD 的 note。要求:origin 远程可访问,并且检出位置是 MQ 分支头部提交;这是合并队列 CI 运行中的常见状态。分离的 HEAD 也可以。

此命令适用于需要了解当前运行是否属于合并队列批次,以及该批次中还有哪些 PR 的 CI 工作流。

常见模式

包含隔离的完整 CI 流水线
jobs:
  test:
    steps:
      - uses: actions/checkout@v4
      - name: Run tests
        run: pytest --junitxml=results.xml
      - name: Upload and evaluate
        if: always()
        run: mergify ci junit-process results.xml
        env:
          MERGIFY_TOKEN: ${{ secrets.MERGIFY_TOKEN }}
使用 scopes 进行选择性测试
jobs:
  detect:
    outputs:
      scopes: ${{ steps.scopes.outputs.scopes }}
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - id: scopes
        run: mergify ci scopes --config .mergify.yml

  backend:
    needs: detect
    if: fromJSON(needs.detect.outputs.scopes).backend == 'true'
    steps:
      - run: pytest backend/

评论

支持 Markdown