How GitHub picks a runner
When a job declares runs-on: [self-hosted, gpu, linux], GitHub finds every runner with all three labels. If multiple runners qualify, the first idle one wins. If none, the job queues until one becomes available.
Labels you'll routinely need
- Trust tier —
trusted(only own-org code) vsuntrusted(public PRs). - Resource shape —
gpu,gpu-h100,large-mem,fast-disk. - Location —
region-us,region-kr,internal-network. - Capability versioning —
cuda12,node22. When you upgrade the runner image, change the label so old workflows still target the old runner during transition.
Group routing
Beyond labels, runners can be in runner groups at the org level. A group restricts which workflows / repos can use that runner. Use groups when one runner pool serves multiple repos with different trust levels.