ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Megatron-LM CI/CD 实战指南:PR Scope 标签、内部 GitLab CI 触发与失败排查

2026/9/14 8:41:17 拓冰建站 浏览量
Megatron-LM CI/CD 实战指南:PR Scope 标签、内部 GitLab CI 触发与失败排查 Megatron-LM CI/CD 实战指南PR Scope 标签、内部 GitLab CI 触发与失败排查【免费下载链接】Megatron-LMOngoing research training transformer models at scale项目地址: https://gitcode.com/GitHub_Trending/me/Megatron-LM本篇技术指南聚焦 Megatron-LM 开源仓库自带的 CI/CD 体系完整讲解 GitHub Actions 主流水线cicd-main.yml的结构与触发逻辑、PR 上各类测试范围标签Run tests、Run functional tests、container::lts等对测试配置的影响、如何用 tools/trigger_internal_ci.py 无 UI 触发内部 GitLab 流水线以及从 CI 分支回溯 PR、读取分片日志、定位失败根因的完整方法。读完本文你将具备CI 变红时该看哪里、开 PR 时该贴哪个标签、如何安全触发内部 CI的实战能力。一、CI/CD 总体概览一条流水线两种触发入口Megatron-LM 的 CI 由一条 GitHub Actions 主工作流 cicd-main.yml 统一驱动其名称即为CICD Megatron-LM。从工作流头部的事件声明cicd-main.yml#L15-L23可以看到它的四种触发来源push 到pull-request/[0-9]分支——这是最核心的路径开发者把本地分支推到远程后CI 据此分支前缀判断这是一个 PR 测试请求push 到deploy-release/*分支——发布/部署工作流merge_groupchecks_requested事件——合并队列merge queue校验workflow_dispatch——手动触发定时任务schedule也在工作流内通过is_ci_workload判断被识别为 CI workload。也就是说CI 是否运行、跑多重的测试并不由 PR 页面的按钮决定而是由分支命名规范 PR 标签label 事件类型三者共同决定。其中pull-request/分支名是贯穿始终的命名约定内部 GitLab 触发工具也会把当前分支强制推送为pull-request/branch这一 ref两个入口最终汇合到同一条流水线上。二、先给结论PR 标签 → 测试配置速查表SKILL 文档给出的首要原则是答案先行Answer-First任何关于该贴什么标签、会跑什么测试的问题都先给出确定性的取值再去解释机制。下表是整个 CI 的第一手事实建议直接作为日常速查情况scopen_repeatlightweight说明未贴任何标签PR push 默认mr-github-slim2false只跑 slim 子集标签Run testsmr-github1true训练 4 步不做 golden-value 对比标签Run functional testsmr-github5false训练 100 步做 golden-value 对比合并队列 merge groupmr-github1false自动生效无需标签三个正交orthogonal标签可在上述任一 scope 之上叠加标签效果container::lts仅把容器镜像路径切换到 LTS 基础镜像与任意 scope 标签组合。opt-in 性质——只在用户明确要求做 LTS 验证时附加任何情况下都不要自作主张添加即使是容器/依赖变更Run MBridge tests额外触发 MBridge L1 测试套件Run NeMoRL tests额外触发 NeMo RL 的 Megatron 功能测试套件一条高危警告tools/trigger_internal_ci.py是破坏性远程写操作SKILL 文档以 ⚠️ 显式标注该脚本会把**当前分支强制推送force-push**到内部 GitLab 远程的pull-request/branchref 上。因此永远先带--dry-run跑一遍确认目标 ref 无误后再去掉该标志绝对不要对共享分支或受保护分支执行只针对你自己的 pull-request 分支安全预检命令python tools/trigger_internal_ci.py --gitlab-origin gitlab --dry-run只有在 dry-run 输出与预期目标一致后才添加可选的--functional-test-*参数。三、CI 流水线结构从 pre-flight 到最终门禁主工作流的任务依赖拓扑SKILL 文档 cicd-main.yml 相互印证如下is-not-external-contributor └─ pre-flight └─ configure # 决定 scope、容器 tag、n_repeat ├─ linting ├─ cicd-container-build │ ├─ cicd-parse-unit-tests → cicd-unit-tests-latest │ ├─ cicd-parse-integration-tests-h100 → cicd-integration-tests-latest-h100 │ └─ cicd-parse-integration-tests-gb200 → cicd-integration-tests-latest-gb200 (maintainers only) └─ Nemo_CICD_Test # 最终 pass/fail 门禁几个关键节点的职责is-not-external-contributor判断 PR 作者是否为 NVIDIA/NVIDIA-NeMo 组织成员或仓库协作者。它既决定后续 GPU runner 的选择maintainer 用nvidia-ci-aws-gpu-x8外部贡献者走 ephemeral runner 路由也决定 GB200 测试是否可跑见 cicd-main.yml#L46-L54。pre-flight复用NVIDIA-NeMo/FW-CI-templates的预检模板输出is_ci_workload、is_merge_group、docs_only、force_run_all等关键判定cicd-main.yml#L177-L180。configure整个流水线的大脑。它一次性读取 PR 的全部标签输出scope、n_repeat、lightweight、lts、mbridge_suite、run_mbridge、run_nemo_rl、cadence等下游所有测试作业共享的配置cicd-main.yml#L182-L393。它还额外做了一件重要的事——Resolve SHA为构建容器、跑测试、比对 golden values 解析出同一个 commit SHAPR push 用合成merge_commit_shamerge group 用head_sha保证容器镜像、golden 值、测试 recipe 永远来自同一次提交。linting跑代码风格检查并额外承担两类守卫——校验 PR 中更新的 golden values 文件格式调用 tools/check_golden_values.py以及检查内核改动是否配套确定性测试调用 tools/check_kernel_determinism_coverage.py见 cicd-main.yml#L439-L473。cicd-integration-gate集成测试的总闸编码了两道独立门禁cicd-main.yml#L888-L939(A) 审批门——cicd-wait-in-queue成功或处于 merge_group / CI workload / force_run_all 豁免场景(B) 单测门——单元测试成功或处于 CI workload / force_run_all 豁免场景。下游四个集成测试矩阵作业消费should_run输出避免重复实现同一套逻辑。Nemo_CICD_Test最终聚合门禁。它汇总单测H100/GB200、集成测试H100/GB200的结果并通过gh run view做全量 job 扫描捕捉任何已结束但失败/取消的矩阵实例cicd-main.yml#L1137-L1256。只有它通过整个工作流才算通过。容器镜像被推送到两个公有云镜像仓库见 cicd-main.yml#L33-L35AWS ECR766267172432.dkr.ecr.us-east-1.amazonaws.com/…H100 测试AWS ECRGB200766267172432.dkr.ecr.us-east-2.amazonaws.com/…GB200 测试maintainer only此外工作流还串联了MBridge 下游测试cicd-mbridge-testing默认对 PR push 关闭、可加Run MBridge tests标签开启成功/失败都会通过 Slack 告警与NeMo RL 下游测试cicd-nemo-rl-testing在NVIDIA-NeMo/RL仓库创建mcore-testing-pr号临时分支后触发其cicd-main.yml结束即删除临时分支以及merge-queue-notification在合并队列校验开始时自动评论 PR 附上运行链接。四、CI 测试范围标签决策树与何时贴什么标签configure作业的真实判定逻辑cicd-main.yml#L253-L269是一个首条命中即生效的 if-elif 决策树与 SKILL 文档中的决策树表格完全一致条件scopen_repeatlightweight备注merge groupL11false自动无需标签标签Run testsL11true训练 4 步、跳过 golden 对比标签Run functional testsL15false训练 100 步、golden 对比CI workload / workflow_dispatchL15false定时、手动、发布触发靠 cadence 区分测试面默认无标签 PR pushL02false仅 slim 子集注意表格中 SKILL 文档用mr-github/mr-github-slim表述工作流源码内部实际使用L1/L0两个 scope 代号二者一一对应。L1对应完整功能测试层functional tierL0对应 slim 子集层。与 scope 并列的还有两条 gating 逻辑cicd-main.yml#L271-L296MBridgePR push 默认关闭merge group、schedule、workflow_dispatch 以及贴上Run MBridge tests标签时开启NeMo RLmerge group 有意跳过PR 作者贴Run NeMoRL tests标签即开启。以及cadence节奏轴cicd-main.yml#L302-L316merge group →mergegroupschedule/dispatch →nightly其余 →pr。Run tests/Run functional tests标签会设置cadence_bypasstrue即标签是对 cadence 过滤的人工覆盖通道——这是贡献者保留的手动指定测试面的出口。cadence 过滤在测试侧由 recipe_parser.py 的filter_by_cadence实现返回 cadence 列表包含请求值的工作负载未声明cadence字段的 recipe 默认对全部触发节奏生效。开 PR 时该贴什么标签SKILL 文档给出了一张按变更性质的推荐表是仓库维护者沉淀的最佳实践变更路径 / 性质应贴标签仅文档docs/、*.md、docstrings无仅 CI/工具.github/、tools/、Makefile无仅测试文件tests/——已有测试、无新 golden valuesRun tests新增测试用例尚无 golden valuesRun functional tests重新启用被禁用的测试-brokenscope → 活跃Run functional tests非数值型库代码日志、错误处理、CLI 参数、重构Run tests可能影响训练数值模型结构、attention、优化器、分布式、MoE 路由Run functional tests容器或依赖变更docker/、pyproject.toml、uv.lockRun tests仅当用户明确要求 LTS 验证时才加container::lts涉及 MBridge 集成加Run MBridge tests可能影响 NeMo RL 与 Megatron 的集成加Run NeMoRL tests经验法则默认贴Run tests当 PR 新增测试用例必须生成 golden values或改动可能移动 loss 曲线时一律用Run functional tests。背后的取舍很直接——lightweighttrue只训练 4 步且不做 golden-value 对比反馈快但无正确性保证lightweightfalse训练 100 步并做 golden-value 对比是数值正确性的权威判据。所谓 golden values即 tests/functional_tests/test_cases/ 下各测试用例目录中的golden_values*.json文件cicd-integration-tests-*作业会把训练结果与之对比。五、触发内部 GitLab CI从本地分支到流水线当需要跑 GitHub CI 之外更重的内部验证如 release 测试、跨平台集群时使用 tools/trigger_internal_ci.py。配套的完整教程见 tools/trigger_internal_ci.md。前置条件1. 添加内部 GitLab 远程已有可跳过git remote -v可查看现有远程git remote add gitlab gitgitlab-hostname:ADLR/Megatron-LM.git之后调用脚本时必须传入--gitlab-origin gitlab与之对应脚本会通过git remote get-url解析主机名源码见 trigger_internal_ci.py#L69-L86支持 SSHgithost:path与 HTTPS URL 两种形式。2. 获取个人访问令牌PAT打开内部 GitLab 个人页User menu → Edit profile → Access tokens点击Add new token填写描述、设置过期时间勾选apiscope创建后复制令牌以glpat-开头存入环境变量避免每次调用都传参export GITLAB_TOKENglpat-your-token建议将令牌写入.env或.bashrc。用法与全部参数python -m pip install python-gitlab python tools/trigger_internal_ci.py \ --gitlab-origin gitlab \ [--access-token glpat-your-token] \ [--functional-test-scope mr] \ [--functional-test-repeat 5] \ [--functional-test-cases all] \ [--functional-test-name release-testing/mcore-vX.Y.Z] \ [--functional-test-time-limit 14400] \ [--dry-run]参数默认值说明--gitlab-origin必填指向内部 GitLab 的 git 远程名--access-token$GITLAB_TOKEN带apiscope 的个人访问令牌--functional-test-scopemrFUNCTIONAL_TEST_SCOPE流水线变量--functional-test-repeat5FUNCTIONAL_TEST_REPEAT流水线变量--functional-test-casesallFUNCTIONAL_TEST_CASES流水线变量--functional-test-namecommit SHAFUNCTIONAL_TEST_NAME流水线变量——为pre-release/releasescope 的运行命名用作运行名与 WB 实验名--functional-test-time-limit依 scope 而定FUNCTIONAL_TEST_TIME_LIMIT流水线变量秒。release/weekly长任务默认144004 小时其余 scope 不设置--dry-run关闭只打印将要执行的动作不做 push、不触发流水线从源码看脚本还额外支持--cluster-a100/--cluster-h100/--cluster-gb200三个集群覆盖变量以及两个固定流水线变量UNIT_TESTno、INTEGRATION_TESTnotrigger_internal_ci.py#L38-L41即该入口只驱动功能测试面。时间限制的自动解析逻辑见resolve_time_limittrigger_internal_ci.py#L51-L66。release 测试约定--functional-test-scope release并按release-testing/mcore-vX.Y.Z命名例如release-testing/mcore-v0.17.0。完整示例# 干跑——不推送、不触发 python tools/trigger_internal_ci.py --gitlab-origin gitlab --dry-run # 真实运行——令牌从环境变量读取 python tools/trigger_internal_ci.py --gitlab-origin gitlab # release 测试——release scope 命名运行 python tools/trigger_internal_ci.py \ --gitlab-origin gitlab \ --functional-test-scope release \ --functional-test-name release-testing/mcore-v0.17.0预期行为Current branch: my-feature-branch Everything up-to-date Triggering pipeline on https://gitlab-hostname project 19378 pull-request/my-feature-branch Pipeline triggered: https://gitlab-hostname/namespace/project/-/pipelines/123456脚本的完整执行流程与 trigger_internal_ci.py#L213-L255 源码一一对应用git rev-parse --abbrev-ref HEAD探测当前分支把分支以pull-request/branch形式 force-push 到 GitLab 远程对应源码git push origin HEAD:pull-request/branch --force用 python-gitlab 在固定项目 ID19378上、以该 ref 触发流水线并注入配置的测试变量打印新建流水线的 URL。六、CI 失败排查从红了到根因CI 分支永远遵循pull-request/数字命名模式这是所有排查的起点。6.1 从 CI 分支定位 PR# 从当前分支提取 PR 号 PR_NUMBER$(git rev-parse --abbrev-ref HEAD | grep -oP (?pull-request/)\d) # 拉取 PR 元数据标题、标签、作者、基础分支 gh pr view $PR_NUMBER --repo NVIDIA/Megatron-LM # 查看该 PR 的变更集 gh pr diff $PR_NUMBER --repo NVIDIA/Megatron-LM6.2 读取 CI 作业日志# 列出该 PR 最近的 workflow 运行 gh run list --repo NVIDIA/Megatron-LM --branch pull-request/$PR_NUMBER # 流式查看失败作业输出 gh run view run-id --repo NVIDIA/Megatron-LM --log-failed关键事实各 rank 的完整日志不在 runner 的 stdout 里而是作为 GitHub artifact 上传命名形如logs-test_case-run_id-uuid。因此要看完整日志必须下载 artifact# 1. 找到 artifact 名称 gh run view run-id --repo NVIDIA/Megatron-LM --json artifacts \ --jq .artifacts[].name # 2. 下载 artifact zip gh run download run-id --repo NVIDIA/Megatron-LM \ --name logs-artifact-name -D ./ci-logs # 3. 定位哪些 rank 的日志包含错误 grep -r -l ERROR\|Traceback\|FAILED\|fatal ./ci-logs/ # 4. 日志可能超过 10000 行——绝不一次性读完整份日志 wc -l ./ci-logs/test/attempt/attempt_0/rank/stderr.log sed -n 1,200p ./ci-logs/.../stderr.log # 分段阅读6.3 定位失败根因的分类清单失败类型处置方法Linting 失败本地重跑 tools/autoformat.shdiff 会精确指出需要修改的位置。该脚本对megatron/core/与tests/下相对基础分支变更的.py文件依次执行 black、isort、pylint、ruff、mypyautoformat.sh#L20-L43容器构建失败检查cicd-container-build作业日志单元测试失败失败的 bucket 在cicd-unit-tests-latest作业的矩阵里。注意单测用例矩阵由 tests/test_utils/recipes/h100/unit-tests.yaml 解析生成功能测试失败看cicd-integration-tests-*作业从 rank 0 的stdout.log开始Flaky 测试runner 会自动重试最多 3 次若重试耗尽且报错模式符合已知瞬态NCCL、ECC、segfault可判定为基础设施噪声此外功能测试作业本身带有错误提取机制generate_jet_trigger_job.py会把测试命令的 stdout 同时 tee 到jet_workload.log并调用extract-errors工具生成结构化的error_report.jsongenerate_jet_trigger_job.py#L16-L31排查时可优先查看这两份文件。6.4 把失败与 PR 变更集关联起来# 找到覆盖某被改动源文件的单元测试 grep -r from megatron.core.transformer.attention tests/unit_tests/ -l # 查询 CODEOWNERS确认该路径的 reviewer 分配 cat .github/CODEOWNERS | grep changed-path这一节把失败的测试与改动的代码建立直接映射是判断我的 PR 是否该为此负责的最快路径。七、源码视角CI 决策的完整证据链理解整个 CI/CD 体系后值得把几处配置→实现的对应关系梳理清楚方便后续按图索骥标签 → 测试配置configure作业通过gh pr view --json labels一次性拉取全部标签再用jq逐一判定HAS_RUN_TESTS/HAS_RUN_FUNCTIONAL/HAS_LTS/HAS_MBRIDGE/HAS_NEMO_RLcicd-main.yml#L245-L251随后按决策树输出配置并把决策结果连同表格写入$GITHUB_STEP_SUMMARY也就是说每次 CI 运行的 step summary 里都有一份本次为何跑这个 scope的审计痕迹。scope/cadence → 测试面解析作业调用 generate_jet_trigger_job.py 生成 GitLab 作业清单--scope、--enable-lightweight-mode、--cadence三个参数直接来自configure的输出cadence 过滤最终落到 recipe_parser.py 的filter_by_cadence。而每份 recipe如 tests/test_utils/recipes/h100/gpt.yaml内部每个 test_case 通过scope:与cadence:字段声明自己属于哪个层、在哪个节奏下运行——例如scope: [mr, mr-github]表示该用例在 PR 与 merge group 场景运行scope: [nightly]表示仅定时任务运行。golden values 的强制校验linting 阶段会用git diff找出变更的golden_values*.json若存在则必须通过 tools/check_golden_values.py 的格式校验cicd-main.yml#L439-L457。这解释了为何新增测试用例必须贴Run functional tests——只有完整功能测试才会生成并回写这些 golden 文件。多平台矩阵单测与集成测试各自按 H100AWS ECR us-east-1与 GB200AWS ECR us-east-2、maintainer only、受ENABLE_GB200_TESTING变量控制两套矩阵并行fail-fast: false保证单个 bucket 失败不会拖垮整批。八、结语Megatron-LM 的 CI/CD 体系可以概括为三句话分支命名定入口标签定范围日志定位失败。日常开发只需记住三个动作——开 PR 时默认贴Run tests、动数值相关代码贴Run functional tests、触发内部 CI 前永远先--dry-run排查问题时沿着pull-request/号→gh pr view→ 下载logs-*artifact → 按失败类型对照清单的顺序走即可。这些结论均可在仓库的 skills/mcore-cicd/SKILL.md、.github/workflows/cicd-main.yml 与 tools/trigger_internal_ci.py 中直接复现验证。【免费下载链接】Megatron-LMOngoing research training transformer models at scale项目地址: https://gitcode.com/GitHub_Trending/me/Megatron-LM创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考