Skip to content

Pools and labels

A runner pool groups runners that are interchangeable. It has:

Property Meaning
name Referenced by CLI, API and Infrastructure
kind self_hosted (yours) or hosted (managed)
executor shell, docker or kubernetes
scope org (usable by every project) or project
labels Labels every runner in the pool advertises
registration token Lets a new runner join the pool
Terminal window
slipway runner pool create linux-docker --executor docker --label os=linux --label gpu
slipway runner pool create k8s-prod --executor kubernetes --scope project -p payments
slipway runner pool list
slipway runner token linux-docker # prints a registration token once

A runner’s status is online, offline, busy or draining. Draining runners finish current jobs and take no new ones.

Jobs choose runners with runs_on, a list of labels. A runner is eligible only if it has all the labels listed.

defaults:
runs_on: [linux, x64]
jobs:
- name: test
runs_on: [linux, x64, docker] # needs a runner with all three
- name: gpu-tests
runs_on: [linux, gpu]

Labels come from the pool and from the runner’s own --labels (comma separated, SLIPWAY_RUNNER_LABELS). Use them for:

  • OS and arch: linux, windows, macos, x64, arm64
  • Capability: docker, gpu, large-disk
  • Trust zone: prod-network, pci, untrusted-prs
  • Team ownership: team-payments

runs_on labels are checked against the pools the project can use: a pool serves a job when its own labels cover runs_on, or when one of its online runners reports labels that, with the pool’s, cover it (every runner reports its OS, architecture and executor, so a pool with no labels still serves runs_on: [linux] while a Linux runner is online). slipway validate warns about labels nothing provides.

While a job cannot be placed it stays pending or queued with a reason on the job and on the run: “no runner pool covers runs_on [linux gpu]”, “waiting for an online runner in pool build with labels [gpu]”, “pool build is at its concurrency limit (2)”. The run detail, the job panel and slipway run watch show it; after the queue timeout (six hours by default) the job fails with no_matching_pool or queue_timeout. Fix it with slipway runner pool update <pool> --add-label gpu, or by starting a runner that reports the label.

--concurrency (default 1) is the number of jobs one runner process runs at once. Plan concurrency limits cap the total running jobs for the org: Free 10 self-hosted and 3 hosted, Team 50 and 15, Business 250 and 60, Enterprise unlimited and negotiated.

Separate trusted and untrusted work. Run pull-request jobs from forks on an ephemeral Kubernetes pool with no secrets and no network route to production; run deployments on a pool inside the production network.

jobs:
- name: test
runs_on: [linux, untrusted]
- name: deploy
runs_on: [linux, prod-network]
environment: { name: production, service: api }

Put runners near the target. An Infrastructure names a runner_pool_id. Deployments for that target run on that pool, inside the network that owns the cluster or account, so credentials never leave it.

Scale to zero. With the Kubernetes executor, jobs are pods; the cluster autoscaler adds and removes nodes. No idle runners to pay for.