将 GitHub CI 迁移到 Hugging Face Jobs
Migrating Your GitHub CI to Hugging Face Jobs
本文介绍了如何将 GitHub Actions 的 CI 作业迁移到 Hugging Face Jobs 上运行,以解决 GitHub Actions 速度慢、缺乏 GPU 支持等问题。通过使用 huggingface/jobs-actions 桥接,将 GitHub Actions 的 job 转为临时自托管运行器:GitHub App 监听 `workflow_job.queued` webhook,dispatcher Space 验证后启动对应硬件(CPU 或 t4-small、h200 等 GPU)的 HF Job,由 ephemeral runner 执行 CI 并上报结果。作者基于 Trackio 项目实际落地,CPU 作业时间减少约 30%,并新增了 GPU 测试套件。文章分步说明了复制 dispatcher Space、创建并安装 GitHub App、配置 webhook 和 HF_TOKEN 的具体步骤。
HF 直接把 CI 桥接器开源了出来,教你把 GitHub Actions 迁到 HF Jobs 上跑 GPU 测试,ML 项目终于可以低成本配上显卡 CI,步骤清晰到能直接抄作业。
如果你有一个 GitHub 仓库并且启用了 GitHub Actions,你很可能在用 GitHub 托管的 runner 来跑 CI。很多项目都采用这个默认设置,因为它很简单:添加一个 workflow,写好 runs-on: ubuntu-latest,GitHub 就会给你一台机器。这个默认方案很方便,但也有局限。GitHub Actions 可能很慢或因维护而停机,托管的机器是通用型的,而 GPU 访问对大多数开源项目来说也不是随开随用的东西。对于 Trackio,这些局限逐渐成了问题。我们既需要可靠的 CPU CI 来跑基本的单元测试和前端检查,也需要 GPU CI 来跑那些必须在真实 CUDA 硬件上运行的测试。
于是我们构建了一个替代方案:让 GitHub Actions 继续负责 CI,但在 Hugging Face Jobs 上运行这些任务。
结果是:Trackio 的 CI 现在运行在 Hugging Face Jobs 上并实时回传日志,CPU 任务的 CI 时间缩短了约 30%,还启用了一套全新的、可在 GPU 机器上运行的测试套件!
在本文中,我们将一步一步讲解如何为你的 GitHub 仓库重建同样的配置。如果你正在使用智能体,可以直接把这篇文章指给它,因为我们除了面向人类用户的浏览器操作指引外,还提供了 CLI 指令。
让我们先快速介绍一下 Hugging Face Jobs!
什么是 Hugging Face Jobs?
Hugging Face Jobs 让你可以在 Hugging Face 的无服务器基础设施上运行命令或脚本,并支持几乎所有硬件规格。一个 Job 本质上就是:
- 一条要运行的命令
- 一个 Docker 镜像,可来自 Docker Hub 或 Hugging Face Space
- 一种硬件规格,例如 CPU 或
t4-small或h200GPU - 可选的环境变量和密钥
例如,你可以运行:
hf jobs run python:3.12 python -c "print('Hello world')"
或者
hf jobs uv run --flavor a10g-small "https://raw.githubusercontent.com/huggingface/trl/main/trl/scripts/sft.py"
这使得 Jobs 非常适合 CI。CI 任务本来就是命令驱动的,本来就在干净的环境中运行,而且通常能从精确选择合适的硬件中受益。对于 ML 库来说,GPU 场景尤其有吸引力:你可以在真实的 GPU 硬件上运行测试套件,而无需维护自己的常驻 runner。
关键步骤是将 GitHub Actions 连接到 HF Jobs,我们在下文中介绍。
架构
在这个方案中,我们创建了 huggingface/jobs-actions,这是一个小型桥接工具,可以把 GitHub Actions 任务转换成一个在 HF Job 内运行的临时自托管 runner。
完整的流程如下:
- 一个 pull request 会触发一个 GitHub Actions workflow。
- GitHub 会将任何其
runs-on标签不可用的任务排入队列,例如hf-jobs-cpu-upgrade或hf-jobs-t4-small,并通过 GitHub App 向分发器发送一个经过签名的workflow_job.queuedwebhook。 - 分发器 Space 会验证该 webhook,检查是否存在
hf-jobs-*标签,生成一个短期有效的 GitHub runner 注册 token,并在匹配的硬件上启动一个 HF Job。 - 该 HF Job 会启动一个临时性的 GitHub Actions runner,并使用这个一次性 token 向仓库注册该 runner。
- GitHub 将待处理的 workflow 任务分配给该 runner;runner 执行 CI 任务,把状态报告回 GitHub,然后退出。
从 GitHub 的角度看,这只是一个 self-hosted runner。从 Hugging Face 的角度看,它只是一个启动容器来运行仓库 GitHub Actions 中 workflow 步骤的 Job。
第 1 步:复制分发器 Space
首先你需要的是分发器。这是一个小型 Docker Space,它接收 GitHub 的 workflow_job webhook 事件并据此启动 HF Jobs。
先创建这个 Space,因为 GitHub App 需要一个 webhook URL,而该 URL 来自这个 Space。此 Space 应位于你自己的命名空间下,或位于你有写权限的某个 Hugging Face 组织下。
Web 设置
前往 huggingface/jobs-actions-dispatcher,并点击 Duplicate this Space(复制此 Space)。
使用:
Owner: your HF user or org
Name: jobs-actions-dispatcher
Hardware: cpu-upgrade
使用 cpu-upgrade 来运行真正的 CI,这样调度器(dispatcher)可以持续保持在线以接收 GitHub webhooks。cpu-basic 用于测试没问题,而且大概率也能正常工作,但它在闲置后可能会进入休眠;如果 GitHub 的 webhook 在它唤醒过程中到达,工作流可能会一直处于排队状态。
构建完成后,打开复制出来的 Space。你会看到一个标有 "Required Space secrets"(必填 Space 密钥)的区域,目前可以先忽略它。落地页应显示你在下一步所需的 GitHub App webhook URL。它看起来是这样的:
https://YOUR-HF-NAMESPACE-jobs-actions-dispatcher.hf.space/webhook
CLI 设置
如果你想通过智能体(agent)或 CLI 工作流来设置调度器 Space:
export HF_NAMESPACE=your-hf-user-or-org
export SPACE_ID="$HF_NAMESPACE/jobs-actions-dispatcher"
hf repo duplicate huggingface/jobs-actions-dispatcher "$SPACE_ID" \
--type space \
--flavor cpu-upgrade \
--exist-ok
然后设置:
export DISPATCHER_URL="https://${HF_NAMESPACE}-jobs-actions-dispatcher.hf.space"
第 2 步:创建并安装 GitHub App
接下来,从调度器 Space 本身创建并安装 GitHub App。该 App 需要权限来监听排队中的工作流任务,并创建临时的 self-hosted runner 注册 token。
Web 设置
打开你复制的调度器 Space:
https://YOUR-HF-NAMESPACE-jobs-actions-dispatcher.hf.space
在设置表单中,输入你希望在 HF Jobs 上运行 CI 的 GitHub 仓库:
YOUR-GITHUB-ORG/YOUR-REPO
然后点击按钮创建 GitHub App。GitHub 会要求你为 App 选择一个名称;名称可以是任何内容,只要在你的 GitHub 账号或组织中可用即可。提交后,最后一屏会准确告诉你如何使用 hf CLI 将 App 凭证上传到调度器 Space。
重要提示:你需要提供一个具有启动 Jobs 权限的 Hugging Face token,对应你的个人账号或需要承担 Jobs 费用的组织。该 token 应在你的调度器 Space 中保存为 HF_TOKEN secret。
最后,你需要在 Space 中填写的同一个 GitHub 仓库上安装该 App。在 Trackio 的设置中,我们将其安装在 gradio-app/trackio 上。
借助智能体协助的设置
GitHub App 的 manifest 流程仍然是基于浏览器的,但智能体可以遵循同样的 Space 驱动路径:
export HF_NAMESPACE=your-hf-user-or-org
export GITHUB_REPO=YOUR-GITHUB-ORG/YOUR-REPO
open "https://${HF_NAMESPACE}-jobs-actions-dispatcher.hf.space"
将 $GITHUB_REPO 粘贴到 Space 中,点击 GitHub App 创建按钮,选择任意可用的 App 名称,然后按照生成的 GitHub 指引操作。
App 创建完成后,在 App 设置页面将其安装到你的仓库上。对于 GitHub 组织,安装设置位于:
https://github.com/organizations/YOUR-GITHUB-ORG/settings/installations
步骤 3:最终调度器设置
此时,调度器 Space 应已完成配置。GitHub 应用的设置流程会生成相关命令,用于将应用凭据、webhook 密钥和 Hugging Face token 上传到该 Space。
默认情况下,HF Jobs 会在与调度器 Space 相同的命名空间下启动。如果希望将任务计费到其他 Hugging Face 用户或组织,可以选择性地将
HF_NAMESPACE 设置为 Space 变量:
export SPACE_ID=YOUR-HF-NAMESPACE/jobs-actions-dispatcher
hf spaces variables add "$SPACE_ID" -e HF_NAMESPACE=your-billing-namespace
hf spaces restart "$SPACE_ID"
你在步骤 2 中设置的 token 应与该命名空间对应。
步骤 4:更改 runs-on
实际的工作流更改很小。不用这样:
runs-on: ubuntu-latest
改用调度器处理的某个标签:
runs-on: hf-jobs-cpu-upgrade
对于 GPU 测试,请使用 GPU 标签:
runs-on: hf-jobs-t4-small
对于任何你想在 HF Jobs 上运行的 GitHub Action,只需这一行更改即可!
步骤 5:测试一下
通过 CLI 添加一个最小化的冒烟测试工作流:
mkdir -p .github/workflows
cat > .github/workflows/hf-jobs-test.yml <<'EOF'
name: HF Jobs Test
on:
pull_request:
push:
branches: [main]
workflow_dispatch:
jobs:
test:
runs-on: hf-jobs-cpu-upgrade
steps:
- uses: actions/checkout@v4
- run: echo "Hello from Hugging Face Jobs"
EOF
git add .github/workflows/hf-jobs-test.yml
git commit -m "Run CI on Hugging Face Jobs"
git push
通过 CLI 进行验证:
gh run list --repo YOUR-GITHUB-ORG/YOUR-REPO --limit 5
hf jobs ps --namespace "$HF_NAMESPACE"
hf spaces logs "$SPACE_ID"
你应该能够看到与普通 GitHub Action 一样的日志——例如,在这个 Trackio PR #565 中。
就这么简单!
关于选择合适 Docker 镜像的说明
我们最初的 CPU 配置使用了 ubuntu:22.04,并在每次运行时安装缺失的系统软件包。这虽然可行,但速度比必要的要慢。GitHub 的 ubuntu-latest 镜像默认包含大量开发者工具;而裸的 Ubuntu 镜像则没有。
对于 Trackio 来说,UI 测试需要 Playwright 浏览器、Node、ffmpeg、sqlite、git 以及常规的 Linux 构建依赖。Hugging Face Jobs 支持使用任意 Docker 镜像,因此我们切换到了 Microsoft Playwright 镜像,效果很好:
mcr.microsoft.com/playwright:v1.60.0-jammy
对于 GPU 任务,我们使用了:
nvidia/cuda:12.4.0-runtime-ubuntu22.04
结果
以下是 Trackio CI 的数据:
| Runner 配置 | 运行时长 | 与 GitHub 平均水平对比 |
|---|---|---|
GitHub ubuntu-latest 基线 | 1m40s | 基线 |
| HF Jobs CPU,Playwright 镜像 | 1m10s | -30s,快约 30% |
HF Jobs GPU,t4-small 标签 | 45s | 无 GitHub 托管 GPU 基线 |
最大的收获是 GPU CI。Trackio 的 GPU 检查在 HF Jobs 上运行,用时 45s 即通过,按该时长的 t4-small 费率计算花费不到一美分。
CPU 的结果同样令人鼓舞。使用合适的镜像,Linux 测试任务比 GitHub 托管基线更快。这表明 HF Jobs 可以成为一个实用的 CI 后端,尤其对于需要自定义镜像或加速器的 ML 项目。
日志是另一个意外的惊喜。GitHub Actions 的日志很有用,但对于大型日志,网页 UI 可能比较笨重。HF Jobs 的日志可以很方便地通过 CLI 获取:
hf jobs logs <job_id> > logs.txt
这使得它们可以用本地工具或编程智能体轻松查看。在我们的桥接方案中,我们还将 GitHub Actions 的任务日志镜像到了 HF Job 日志中,因此任何一个系统都有足够的信息来调试一次运行。
最后,虽然 Trackio 的 CI 并不需要,HF Jobs 还 支持挂载卷,如果你需要在 CI 中快速从 Hugging Face 加载数据集或模型,这会非常有用。
希望这些内容足以让你尝试用 HF Jobs 来运行你的 GitHub Actions!
来源:Hugging Face:Blog(RSS) · huggingface.co