| 名称 | mcore-create-issue |
| 描述 | 调查失败的GitHub Actions运行或任务,并为失败创建GitHub问题。 |
| 开源协议 | Apache-2.0 when_to_use: 用户分享GitHub Actions URL并希望提交错误报告;‘为此次失败创建issue’,‘为此次CI运行提交bug’,‘对此次GitHub Actions失败进行分类’。 user_invocable: true argument: “GitHub Actions运行或任务URL” metadata: |
| 作者 | Philip Petrakian ppetrakian@nvidia.com |
将CI失败分类并创建GitHub Issue
调查失败的GitHub Actions任务,提取根本原因,并向NVIDIA/Megatron-LM提交结构良好的错误问题。
工作流
1. 解析URL
参数是GitHub Actions URL。它将是以下之一:
- 任务URL:
https://github.com/<owner>/<repo>/actions/runs/<run_id>/job/<job_id> - 运行URL:
https://github.com/<owner>/<repo>/actions/runs/<run_id>
提取run_id,如果存在,则提取job_id。
2. 识别失败的任务
-
如果提供了
job_id,直接使用该任务。 -
如果仅提供了
run_id,列出运行中所有失败的任务:gh run view <run_id> --repo NVIDIA/Megatron-LM --json jobs \ --jq '[.jobs[] | select(.conclusion == "failure") | {id: .databaseId,
name: .name, url: .url}]’
如果有多个任务失败,询问用户要分类哪一个,或者如果他们要求,可以全部分类。
### 3. 获取失败日志
对于每个失败的任务,检索日志并将其缩小到失败部分:
```bash
# 拉取原始日志并仅保留包含错误的行
gh api repos/NVIDIA/Megatron-LM/actions/jobs/<job_id>/logs 2>&1 \
| grep -E "(FAILED|ERROR|\bError\b|assert|Traceback|Exception|##\[error\])" \
| head -200
同时捕获完整任务名称:
gh run view --job <job_id> --repo NVIDIA/Megatron-LM --json name --jq .name
如果grep输出稀疏,下载完整日志并查找pytest的FAILURES部分或最后一个非零退出信号。
4. 解析触发的PR和测试作者
触发的PR: 运行的头分支遵循模式pull-request/<number>。提取并解析PR:
gh run view <run_id> --repo NVIDIA/Megatron-LM --json headBranch --jq .headBranch
# → 例如 "pull-request/4332"
# 提取PR编号并获取元数据:
gh pr view <pr_number> --repo NVIDIA/Megatron-LM --json number,title,url \
--jq '{number: .number, title: .title, url: .url}'
测试文件作者: 找到最后修改失败测试文件的GitHub登录名。该文件可能不存在于main上——首先确定PR的基础分支,然后从该分支搜索:
# 1. 获取PR的基础分支(例如 "main"、"dev"、"release/X.Y")
gh pr view <pr_number> --repo NVIDIA/Megatron-LM --json baseRefName --jq .baseRefName
# 2. 在该基础分支上搜索提交
gh api "repos/NVIDIA/Megatron-LM/commits?path=<test-file-path>&sha=<base-branch>&per_page=1" \
--jq '.[0] | {login: .author.login,
name: .commit.author.name, sha: .sha}'
如果结果为空(文件是由PR本身引入的),则查询PR的提交:
gh api "repos/NVIDIA/Megatron-LM/pulls/<pr_number>/commits" \
--jq '[.[] | select(.files? // [] | any(.filename == "<test-file-path>"))] | .[0].author.login'
作为最后手段,列出PR提交并选择提交消息与失败测试文件最相关的作者。
5. 提取根本原因
从日志中,识别:
- 失败的测试: 匹配
FAILED tests/...::...的行给出确切的pytest节点ID。 - 错误消息: 断言失败、异常类型或第一个有意义的堆栈帧——保持在大约30行以内。
- 任务名称: GitHub Actions任务名称(例如
tests/unit_tests/transformer/moe/**/*.py - latest)。 - 运行/任务URL 和 PR URL: 用于在问题中链接。
6. 检查重复问题
搜索是否已有覆盖相同测试的开放问题:
gh issue list --repo NVIDIA/Megatron-LM \
--state open \
--search "<failed-test-filename>" \
--json number,title,url \
--limit 10
- 如果存在匹配的开放问题,不要创建新问题。向用户报告现有问题并停止。
- 如果没有找到匹配项,则继续提交新问题。
7. 创建问题
传递--assignee <test-author-login>将问题分配给测试文件的作者。在问题正文中包含触发的PR URL。
gh issue create \
--repo NVIDIA/Megatron-LM \
--title "🐛 CI failure: <failed-test-node-id>" \
--label "bug" \
--assignee "<test-author-login>" \
--body "..."
使用错误报告模板正文结构:
**描述错误**
CI测试 `<failed-test-node-id>` 在任务 [`<job-name>`](<job-url>) 中失败。
标记 @NVIDIA/mcore-oncall 以引起值班人员对此问题的注意。
**失败的运行**
| 字段 | 值 |
|-------|-------|
| PR | [#<pr_number>: <pr_title>](<pr_url>) |
| 运行 | [<run_id>](<run_url>) |
| 任务 | [<job_name>](<job_url>) |
**错误**
<核心错误消息 / 堆栈回溯 — 最多30行>
**重现错误的步骤/代码**
重新运行上述失败的CI任务,或在开发容器中本地运行:
```bash
pytest <failed-test-node-id>
其他上下文
通过 /triage-issue 自动分类。
如果同一任务中有多个测试失败,请在“描述错误”下将每个测试列为单独的要点,并包含合并的错误片段。将问题分配给失败列表中第一个出现的测试文件的作者。
### 8. 向用户报告
打印新创建问题(或重复问题,如果找到)的URL,以便用户查看或分享。
## 重要指南
- 如果重复问题已存在,切勿创建新问题——而是链接现有问题。
- 始终在问题正文中包含触发的PR链接。
- 始终将问题分配给测试文件的最近作者。如果作者查找失败(例如提交由机器人完成或登录名不可用),则跳过`--assignee`并在“其他上下文”部分注明。
- 保持错误片段简洁(≤30行)。截断较长的堆栈回溯,并说明完整日志可通过任务URL获取。
- 不要猜测根本原因——逐字引用实际日志输出。
- 如果任务仍在进行中或日志不可用,请说明并要求用户在运行完成后重试。