AI News HubLIVE
原文8 min read

Migrating Your GitHub CI to Hugging Face Jobs

This article explains how to migrate GitHub Actions CI to Hugging Face Jobs to overcome limitations of GitHub-hosted runners, such as slow speed and lack of GPU access. By setting up a dispatcher Space, a GitHub App, and modifying the runs-on label, CI jobs can run on Hugging Face infrastructure with CPU or GPU hardware, streaming logs in real-time. Trackio's experience shows a ~30% reduction in CPU job time.

Back to Articles

Migrating Your GitHub CI to Hugging Face Jobs

Published June 9, 2026

Update on GitHub

Upvote

8

Abubakar Abid

abidlabs

If you have a GitHub repository and you have GitHub Actions enabled, you probably use GitHub-hosted runners for CI. That is the default for many projects because it is simple: add a workflow, write runs-on: ubuntu-latest, and GitHub gives you a machine.

That default is convenient, but it also has limits. GitHub Actions can be slow or down for maintenance, the hosted machines are generic, and GPU access is not something most open-source projects can just turn on. For Trackio, those limits started to matter. We wanted both reliable CPU CI for basic unit tests and frontend checks, but also GPU CI for tests that need to run on actual CUDA hardware.

So built an alternative: keep GitHub Actions in charge of CI, but run the jobs on Hugging Face Jobs.

The result: Trackio's CI now runs on Hugging Face Jobs and streams back real-time logs, cutting our CI time for CPU jobs by about 30% and enabling a whole new test suite that runs on GPU machines!

In this article, we explain step-by-step how to recreate the same setup for your GitHub repo. If you are using an agent, you can point it to this article, since we provide CLI instructions alongside browser-based instructions for us humans.

Let's start with a quick intro to Hugging Face Jobs!

What is Hugging Face Jobs?

Hugging Face Jobs lets you run commands or scripts on Hugging Face's serverless infrastructure with almost any hardware flavor. A Job is essentially:

a command to run

a Docker image, from Docker Hub or a Hugging Face Space

a hardware flavor, such as CPU or t4-small or h200 GPU

optional environment variables and secrets

For example, you can run:

hf jobs run python:3.12 python -c "print('Hello world')"

or

hf jobs uv run --flavor a10g-small "https://raw.githubusercontent.com/huggingface/trl/main/trl/scripts/sft.py"

That makes Jobs a natural fit for CI. CI jobs are already command-driven, already run in clean environments, and often benefit from choosing exactly the right hardware. For ML libraries, the GPU case is especially compelling: you can run a test suite on real GPU hardware without maintaining your own always-on runner.

The key step is connecting GitHub Actions to HF Jobs, which we describe below.

The architecture

For this setup, we created huggingface/jobs-actions, a small bridge that turns a GitHub Actions job into an ephemeral self-hosted runner running inside an HF Job.

The complete flow looks like this:

A pull request triggers a GitHub Actions workflow.

GitHub queues any job whose runs-on label is not available, for example hf-jobs-cpu-upgrade or hf-jobs-t4-small, and sends a signed workflow_job.queued webhook to the dispatcher through the GitHub App.

The dispatcher Space verifies the webhook, checks for an hf-jobs-* label, mints a short-lived GitHub runner registration token, and starts an HF Job on the matching hardware.

The HF Job boots an ephemeral GitHub Actions runner and registers it with the repo using that one-shot token.

GitHub assigns the pending workflow job to that runner; the runner executes the CI job, reports status back to GitHub, and exits.

From GitHub's point of view, this is just a self-hosted runner. From Hugging Face's point of view, it is just a Job that launches a container to run the workflow steps from the repo’s GitHub Actions.

Step 1: Duplicate the dispatcher Space

The first thing you need is the dispatcher. This is a small Docker Space that receives GitHub workflow_job webhook events and launches HF Jobs in response.

Create this first because the GitHub App needs a webhook URL, and that URL comes from the Space. This Space should be under your own namespace or under a Hugging Face org that you have write access to.

Web setup

Go to huggingface/jobs-actions-dispatcher and click Duplicate this Space.

Use:

Owner: your HF user or org Name: jobs-actions-dispatcher Hardware: cpu-upgrade

Use cpu-upgrade for real CI so the dispatcher stays available for GitHub webhooks. cpu-basic is fine for testing and will probably work, but it can sleep after inactivity; if GitHub's webhook arrives while it is waking up, the workflow may stay queued forever.

After it builds, open the duplicated Space. You will see a section that says "Required Space secrets," which you can ignore for now. The landing page should display the GitHub App webhook URL you need in the next step. It will look like this:

https://YOUR-HF-NAMESPACE-jobs-actions-dispatcher.hf.space/webhook

CLI setup

If you'd prefer to set up the dispatcher Space with an agent or use a CLI workflow:

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

Then set:

export DISPATCHER_URL="https://${HF_NAMESPACE}-jobs-actions-dispatcher.hf.space"

Step 2: Create and install the GitHub App

Next, create and install the GitHub App from the dispatcher Space itself. This App needs permission to listen for queued workflow jobs and create ephemeral self-hosted runner registration tokens.

Web setup

Open your duplicated dispatcher Space:

https://YOUR-HF-NAMESPACE-jobs-actions-dispatcher.hf.space

In the setup form, enter the GitHub repo whose CI should run on HF Jobs:

YOUR-GITHUB-ORG/YOUR-REPO

Then click the button to create the GitHub App. GitHub will ask you to choose a name for the App; the name can be anything, as long as it is available in your GitHub account or org. After you submit, the final screen tells you exactly how to upload the App credentials to the dispatcher Space with the hf CLI.

Important note: you will need to provide an Hugging Face token that has permissions to launch Jobs, corresponding to your personal account or an org under which Jobs should be charged. This token should be saved as the HF_TOKEN secret in your dispatcher Space.

Finally, you will install the App on the same GitHub repo you entered in the Space. In the Trackio setup, we installed it on gradio-app/trackio.

Agent-assisted setup

The GitHub App manifest flow is still browser-based, but an agent can follow the same Space-driven path:

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"

Paste $GITHUB_REPO into the Space, click the GitHub App creation button, choose any available App name, and follow the generated GitHub instructions.

After the App exists, install it on your repo from the App settings page. For a GitHub org, the installation settings are under:

https://github.com/organizations/YOUR-GITHUB-ORG/settings/installations

Step 3: Final dispatcher settings

At this point, the dispatcher Space should be configured. The GitHub App setup flow generated the commands that upload the App credentials, webhook secret, and Hugging Face token to the Space.

By default, HF Jobs are launched under the same namespace as the dispatcher Space. Optionally, set HF_NAMESPACE as a Space variable if you want to bill jobs to a different Hugging Face user or org:

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"

The token you set in Step 2 should correspond to this namespace.

Step 4: Change runs-on

The actual workflow change is small. Instead of:

runs-on: ubuntu-latest

use one of the labels handled by the dispatcher:

runs-on: hf-jobs-cpu-upgrade

For GPU tests, use a GPU label:

runs-on: hf-jobs-t4-small

For any GitHub Action you'd like to run on HF Jobs, this 1-line change is all you need!

Step 5: Test it out

To add a minimal smoke-test workflow from the CLI:

mkdir -p .github/workflows cat > .github/workflows/hf-jobs-test.yml > logs.txt

That makes them easy to inspect with local tools or coding agents. In our bridge, we also mirrored the GitHub Actions job log into the HF Job log, so either system had enough information to debug a run.

Finally, although we didn't need them for Trackio's CI, HF Jobs also supports mounting volumes, which can be very helpful if you need to load datasets or models from Hugging Face quickly as part of your CI.

Hopefully, this gives you all you need to try HF Jobs for running your GitHub Actions!

Spaces mentioned in this article 1

More Articles from our Blog

guidehuboptimization

Learn the Hugging Face Kernel Hub in 5 Minutes

+3

164

June 12, 2025

llmrltrl

Shipping a Trillion Parameters With a Hub Bucket: Delta Weight Sync in TRL

+4

41

May 27, 2026

Community

GitHub CI is limitless and free. In Huggingface now I can't even run more 3 CPU spaces.

\n","updatedAt":"2026-06-12T06:53:06.857Z","author":{"_id":"631a9ec4223d36c57073474c","avatarUrl":"https://cdn-avatars.huggingface.co/v1/production/uploads/1662689222784-631a9ec4223d36c57073474c.png","fullname":"K.L. Λ","name":"k-l-lambda","type":"user","isPro":false,"isHf":false,"isHfAdmin":false,"isMod":false,"followerCount":8,"isUserFollowing":false}},"numEdits":0,"identifiedLanguage":{"language":"en","probability":0.9555311799049377},"editors":["k-l-lambda"],"editorAvatarUrls":["https://cdn-avatars.huggingface.co/v1/production/uploads/1662689222784-631a9ec4223d36c57073474c.png"],"reactions":[],"isReport":false},"replies":[{"id":"6a2bad884e418d5b5d5ec3ce","author":{"_id":"608b8bb39d7c9519b4adae19","avatarUrl":"https://cdn-avatars.huggingface.co/v1/production/uploads/1621947938344-noauth.png","fullname":"Abubakar Abid","name":"abidlabs","type":"user","isPro":true,"isHf":true,"isHfAdmin":false,"isMod":false,"followerCount":1337,"isUserFollowing":false,"primaryOrg":{"avatarUrl":"https://cdn-avatars.huggingface.co/v1/production/uploads/608b8bb39d7c9519b4adae19/LzaB0gCl3G9dCmM9mzYEW.png","fullname":"Gradio","name":"gradio","type":"org","isHf":false,"details":"Making machine learning more accessible through our open-source Python library. Rapidly create UIs to demo & deploy your model. Share with anyone, anywhere.","plan":"team"}},"createdAt":"2026-06-12T06:56:08.000Z","type":"comment","data":{"edited":false,"hidden":false,"latest":{"raw":"Hi @k-l-lambda what error do you see when try to run more than 3 CPU Spaces? Can you share a bit more about your CI setup?\n\n","html":"

Hi @k-l-lambda what error do you see when try to run more than 3 CPU Spaces? Can you share a bit more about your CI setup?

\n","updatedAt":"2026-06-12T06:56:08.557Z","author":{"_id":"608b8bb39d7c9519b4adae19","avatarUrl":"https://cdn-avatars.huggingface.co/v1/production/uploads/1621947938344-noauth.png","fullname":"Abubakar Abid","name":"abidlabs","type":"user","isPro":true,"isHf":true,"isHfAdmin":false,"isMod":false,"followerCount":1337,"isUserFollowing":false,"primaryOrg":{"avatarUrl":"https://cdn-avatars.huggingface.co/v1/production/uploads/608b8bb39d7c9519b4adae19/LzaB0gCl3G9dCmM9mzYEW.png","fullname":"Gradio","name":"gradio","type":"org","isHf":false,"details":"Making machine learning more accessible through our open-source Python library. Rapidly create UIs to demo & deploy your model. Share with anyone, anywhere.","plan":"team"}}},"numEdits":0,"identifiedLanguage":{"language":"en","probability":0.9173112511634827},"editors":["abidlabs"],"editorAvatarUrls":["https://cdn-avatars.huggingface.co/v1/production/uploads/1621947938344-noauth.png"],"reactions":[],"isReport":false,"parentCommentId":"6a2bacd2f9dc3c32e30d5428"}},{"id":"6a2bb084c2edb524d9381427","author":{"_id":"631a9ec4223d36c57073474c","avatarUrl":"https://cdn-avatars.huggingface.co/v1/production/uploads/1662689222784-631a9ec4223d36c57073474c.png","fullname":"K.L. Λ","name":"k-l-lambda","type":"user","isPro":false,"isHf":false,"isHfAdmin":false,"isMod":false,"followerCount":8,"isUserFollowing":false},"createdAt":"2026-06-12T07:08:52.000Z","type":"comment","data":{"edited":false,"hidden":false,"latest":{"raw":"> # 403\n\n> You've reached your cpu-basic quota limit, please upgrade your account, or pause your previous Spaces to start this one","html":"

\n

\n\t\n\t\t\n\t\n\t\n\t\t403\n\t\n

\n

\n

\n

You've reached your cpu-basic quota limit, please upgrade your account, or pause your previous Spaces to start this one

\n

\n","updatedAt":"2026-06-12T07:08:52.630Z","author":{"_id":"631a9ec4223d36c57073474c","avatarUrl":"https://cdn-avatars.huggingface.co/v1/production/uploads/1662689222784-631a9ec4223d36c57073474c.png","fullname":"K.L. Λ","name":"k-l-lambda","type":"user","isPro":false,"isHf":false,"isHfAdmin":false,"isMod":false,"followerCount":8,"isUserFollowing":false}},"numEdits":0,"identifiedLanguage":{"language":"en","probability":0.8983129262924194},"editors":["k-l-lambda"],"editorAvatarUrls":["https://cdn-avatars.huggingface.co/v1/production/uploads/1662689222784-631a9ec4223d36c57073474c.png"],"reactions":[],"isReport":false,"parentCommentId":"6a2bacd2f9dc3c32e30d5428"}},{"id":"6a2bb0f6f9dc3c32e30d5431","author":{"_id":"608b8bb39d7c9519b4adae19","avatarUrl":"https://cdn-avatars.huggingface.co/v1/production/uploads/1621947938344-noauth.png","fullname":"Abubakar Abid","name":"abidlabs","type":"user","isPro":true,"isHf":true,"isHfAdmin":false,"isMod":false,"followerCount":1337,"isUserFollowing":false,"primaryOrg":{"avatarUrl":"https://cdn-avatars.huggingface.co/v1/production/uploads/608b8bb39d7c9519b4adae19/LzaB0gCl3G9dCmM9mzYEW.png","fullname":"Gradio","name":"gradio","type":"org","isHf":false,"details":"Making machine learning more accessible through our open-source Python library. Rapidly create UIs to demo & deploy your model. Share with anyone, anywhere.","plan":"team"}},"createdAt":"2026-06-12T07:10:46.000Z","type":"comment","data":{"edited":false,"hidden":false,"latest":{"raw":"Ah okay yes I think we do have this limit in place for non-PRO accounts, sorry about that. I would consider upgrading to PRO as it's quite powerful: https://huggingface.co/pro","html":"

Ah okay yes I think we do have this limit in place for non-PRO accounts, sorry about that. I would consider upgrading to PRO as it's quite powerful: https://huggingface.co/pro

\n","updatedAt":"2026-06-12T07:10:46.621Z","author":{"_id":"608b8bb39d7c9519b4adae19","avatarUrl":"https://cdn-avatars.huggingface.co/v1/production/uploads/1621947938344-noauth.png","fullname":"Abubakar Abid","name":"abidlabs","type":"user","isPro":true,"isHf":true,"isHfAdmin":false,"isMod":false,"followerCount":1337,"isUserFollowing":false,"primaryOrg":{"avatarUrl":"https://cdn-avatars.huggingface.co/v1/production/uploads/608b8bb39d7c9519b4adae19/LzaB0gCl3G9dCmM9mzYEW.png","fullname":"Gradio","name":"gradio","type":"org","isHf":false,"details":"Making machine learning more accessible through our open-source Python library. Rapidly create UIs to demo & deploy your model. Share with anyone, anywhere.","plan":"team"}}},"numEdits":0,"identifiedLanguage":{"language":"en","probability":0.9822119474411011},"editors":["abidlabs"],"editorAvatarUrls":["https://cdn-avatars.huggingface.co/v1/production/uploads/1621947938344-noauth.png"],"reactions":[],"isReport":false,"parentCommentId":"6a2bacd2f9dc3c32e30d5428"}}]},{"id":"6a2bad7b4e418d5b5d5ec3c8","author":{"_id":"608b8bb39d7c9519b4adae19","avatarUrl":"https://cdn-avatars.huggingface.co/v1/production/uploads/1621947938344-noauth.png","fullname":"Abubakar Abid","name":"abidlabs","type":"user","isPro":true,"isHf":true,"isHfAdmin":false,"isMod":false,"followerCount":1337,"isUserFollowing":false,"primaryOrg":{"avatarUrl":"https://cdn-avatars.huggingface.co/v1/production/uploads/608b8bb39d7c9519b4adae19/LzaB0gCl3G9dCmM9mzYEW.png","fullname":"Gradio","name":"gradio","type":"org","isHf":false,"details":"Making machine learning more accessible through our open-source Python library. Rapidly create UIs to demo & deploy your model. Share with anyone, anywhere.","plan":"team"}},"createdAt":"2026-06-12T06:55:55.000Z","type":"comment","data":{"edited":true,"hidden":false,"latest":{"raw":"Please feel free to drop a comment if you need any help migrating your CI!","html":"

Please feel free to drop a comment if you need any help migrating your CI!

\n","updatedAt":"2026-06-12T06:56:59.065Z","author":{"_id":"608b8bb39d7c9519b4adae19","avatarUrl":"https://cdn-avatars.huggingface.co/v1/production/uploads/1621947938344-noauth.png","fullname":"Abubakar Abid","name":"abidlabs","type":"user","isPro":true,"isHf":true,"isHfAdmin":false,"isMod":false,"followerCount":1337,"isUserFollowing":false,"primaryOrg":{"avatarUrl":"https://cdn-avatars.huggingface.co/v1/production/uploads/608b8bb39d7c9519b4adae19/LzaB0gCl3G9dCmM9mzYEW.png","fullname":"Gradio","name":"gradio","type":"org","isHf":false,"details":"Making machine learning more accessible through our open-source Python library. Rapidly create UIs to demo & deploy your model. Share with anyone, anywhere.","plan":"team"}}},"numEdits":1,"identifiedLanguage":{"language":"en","probability":0.9173112511634827},"editors":["abidlabs"],"editorAvatarUrls":["https://cdn-avatars.huggingface.co/v1/production/uploads/1621947938344-noauth.png"],"reactions":[],"isReport":false}}],"status":"open","isReport":false,"pinned":false,"locked":false,"collection":"community_blogs"},"contextAuthors":["abidlabs"],"primaryEmailConfirmed":false,"discussionRole":0,"acceptLanguages":["en","zh"],"withThread":true,"cardDisplay":false,"repoDiscussionsLocked":false,"hideComments":true}">

k-l-lambda

about 7 hours ago

GitHub CI is limitless and free. In Huggingface now I can't even run more 3 CPU spaces.

·

abidlabs

Article author about 7 hours ago

Hi @k-l-lambda what error do you see when try to run more than 3 CPU Spaces? Can you share a bit more about your CI setup?

abidlabs

Article author about 7 hours ago

edited about 7 hours ago

Please feel free to drop a comment if you need any help migrating your CI!

Upload images, audio, and videos by dragging in the text input, pasting, or clicking here.

Tap or paste here to upload images

· Sign up or log in to comment

Upvote

8

Spaces mentioned in this article 1