Routing and fallback
Route every workflow you move to Hive Runner. A routed job runs on your hive when one of its machines is free and on the runner you use now when none is, so a closed laptop never leaves a job waiting. It is one small job in front of the ones you already have.
The workflow
jobs:
route:
runs-on: ubuntu-latest
permissions:
id-token: write
outputs:
runner: ${{ steps.hive.outputs.runner }}
steps:
- id: hive
uses: thecomputerplumbers/hive-route@v1
with:
label: hive
fallback: ubuntu-latest
test:
needs: route
runs-on: ${{ needs.route.outputs.runner }}
steps:
- uses: actions/checkout@v7
- uses: oven-sh/setup-bun@v2
- run: bun testThe route job runs thecomputerplumbers/hive-route, which asks Hive Runner whether a machine in your hive is free and writes the answer to an output. Every job you want routed takes needs: route and reads that output in runs-on. Nothing else in the job changes.
Inputs and outputs
| Input | Default | What it is |
|---|---|---|
label | hive | The hive label to use when a machine is free. Any label and size. |
fallback | ubuntu-latest | The runner to use when none is. Set it to whatever the job runs on today, including a self-hosted label. |
wait | 15 | Seconds to keep asking before falling back, up to 120. A free machine ends the wait at once. |
| Output | What it is |
|---|---|
runner | The label to give runs-on. |
routed | true when the job goes to your hive, false when it falls back. |
What it checks
A machine counts as free when it is connected, idle, large enough for the label and still enrolled in your hive. A machine that is paused, busy with a job for this or another hive, or revoked does not. The job also falls back when your organization's balance has run out, when the label is not one your hive serves, and when Hive Runner cannot be reached. The step never fails your workflow, and its log says which of these happened.
What it is allowed to do
The step needs id-token: write and nothing else. It uses that to ask GitHub for the job's own OIDC token, which proves to Hive Runner which repository is asking. It reads nothing from the repository. The whole action is one short file with no dependencies; pin it to a commit if you want it never to change under you.
Good to know
- Match the architecture.
hiveis arm64 andubuntu-latestis x64. If a job needs one architecture, fall back toubuntu-24.04-arm, or route to an x64 label such ashive-x64. - It checks; it does not reserve. A machine can leave or take another job between the check and the job being queued. The job then waits in GitHub's queue for a machine, and is not moved to the fallback.
- The wait starts when the route job starts. GitHub still has to start a hosted runner for it first.
- The route job is a GitHub-hosted job. It runs for a few seconds, and GitHub bills a private repository for it as it does any hosted job.
- More than one size. Add a second step to the route job with its own
id,labeland output, and read that output in the jobs that need it.
Without routing
For a job that can wait for a machine, skip the route job and ask for the label directly. It stays queued at GitHub until a machine of the right size is free.
jobs:
test:
runs-on: hive
steps:
- uses: actions/checkout@v7
- uses: oven-sh/setup-bun@v2
- run: bun testNext: Agents and MCP