CI(持续集成)#
slime 使用 GitHub Actions 进行 CI。测试通过 PR label 触发——给 PR 添加特定 label 即可运行对应的测试套件。
工作原理#
工作流定义在 .github/workflows/pr-test.yml(由 pr-test.yml.j2 自动生成)。每个 CI 任务会:
在自托管 GPU runner 上以 Docker 容器(
slimerl/slime:latest)运行。通过
pip install -e . --no-deps安装 slime。通过
tests/ci/gpu_lock_exec.py --count <num_gpus>获取所需数量的 GPU。执行测试文件:
python <test_path>.py或python tests/<test_file>.py。如果测试位于tests/plugin_contracts/这样的子目录,CI 也会自动处理。
每个测试文件遵循统一的模式:prepare() 函数下载模型和数据集,execute() 函数构建命令行参数并调用 U.execute_train(...)。
CI Labels#
给 PR 添加 label 即可触发对应的测试套件:
Label |
Job |
说明 |
|---|---|---|
|
|
Qwen2.5-0.5B 轻量级冒烟测试(4 GPU),用于快速反馈。 |
|
|
核心 Megatron 训练测试,覆盖 Dense、MoE、PPO、MTP、OPD 等。 |
|
|
数值精度校验(并行一致性检查)。 |
|
|
Checkpoint 保存/加载正确性(同步和异步保存)。 |
|
|
在 |
|
|
动态检测 PR 中新增或修改的测试文件,仅运行这些测试。 |
所有 label 也可通过 workflow_dispatch(在 Actions 页面手动触发)来运行。
重点 Label 说明#
run-ci-changed — 仅运行新增或修改的测试#
这是开发中最常用的 label。当你新增或修改了测试文件时,只需给 PR 添加 run-ci-changed,CI 会自动:
检测相对于
origin/main新增或修改的tests/test_*.py或tests/plugin_contracts/test_*.py文件(通过git diff --diff-filter=AM)。提取每个测试文件中的
NUM_GPUS值。构建动态 GitHub Actions matrix,并行运行每个测试。
这意味着你不需要手动在 workflow 中注册新测试——只需确保测试文件顶部有 NUM_GPUS = <N> 常量,run-ci-changed 就会自动识别并运行。
示例:如果你的 PR 新增了 tests/test_qwen3_8B_opd_sglang.py(其中 NUM_GPUS = 8),添加 run-ci-changed label 后会自动在 8 张 GPU 上运行该测试。
run-ci-image — 在测试镜像上运行全部测试#
这会在 slimerl/slime-test:latest Docker 镜像上运行所有已注册的测试。适用于:
验证新构建的 Docker 镜像是否可用。
在合并前做全面的测试检查。
由于包含所有测试,GPU 占用时间较长——日常开发请优先使用更有针对性的 label。
run-ci-megatron — 核心 Megatron 测试#
这是验证 Megatron 后端改动的主要 label,覆盖:
Dense 模型:GLM4-9B、Qwen3-4B(PPO)
MoE 模型:Qwen3-30B-A3B(有/无 DeepEP + FP8)、Moonlight-16B-A3B
特殊场景:MiMo-7B MTP、Qwen2.5-0.5B debug rollout-then-train、OPD(sglang teacher 模式)
所有测试使用 8 张 GPU。如果你正在修改 Megatron 训练逻辑、loss 计算或 checkpoint 转换,应该使用这个 label。
编写新测试#
创建
tests/test_<your_test_name>.py,遵循标准模式:
import os
import slime.utils.external_utils.command_utils as U
MODEL_NAME = "Qwen2.5-0.5B-Instruct"
MODEL_TYPE = "qwen2.5-0.5B"
NUM_GPUS = 4 # 此常量会被 run-ci-changed 自动读取
def prepare():
U.exec_command("mkdir -p /root/models /root/datasets")
U.exec_command(f"huggingface-cli download Qwen/{MODEL_NAME} --local-dir /root/models/{MODEL_NAME}")
# 按需下载数据集 ...
def execute():
# 构建参数字符串并调用 U.execute_train(...)
...
if __name__ == "__main__":
prepare()
for proxy_var in ("http_proxy", "https_proxy", "HTTP_PROXY", "HTTPS_PROXY"):
os.environ.pop(proxy_var, None)
execute()
快速验证:直接推送测试文件,给 PR 添加
run-ci-changedlabel,测试会被自动检测并运行。注册到固定 label 组:编辑
.github/workflows/pr-test.yml.j2,在对应 job 的tests列表中添加条目,然后重新生成:
cd .github/workflows && python generate_github_workflows.py
记得同时提交 .j2 和生成的 .yml 文件。
Workflow 生成#
工作流文件 pr-test.yml 是从 Jinja2 模板 pr-test.yml.j2 自动生成的。不要直接编辑 pr-test.yml。修改步骤:
编辑
.github/workflows/pr-test.yml.j2。运行
python .github/workflows/generate_github_workflows.py。同时提交两个文件。
Customization 契约测试#
如果你要运行通过函数路径加载的 customization hook 契约测试,可以使用:
python -m pytest \
tests/plugin_contracts/test_plugin_rollout_contracts.py \
tests/plugin_contracts/test_plugin_generate_contracts.py \
tests/plugin_contracts/test_plugin_path_loading_contracts.py \
tests/plugin_contracts/test_plugin_runtime_hook_contracts.py
这些测试文件也支持直接执行 python tests/plugin_contracts/<file>.py。它们声明了 NUM_GPUS = 0,因此可以被 run-ci-changed 自动识别,同时不会被当作 GPU 重型端到端测试。