CI

Runner providers

A runner provider is a service or autoscaler that starts a fresh runner for each queued job and throws it away afterwards. This page says which ones work with GitCafe Actions and how a runner service connects to GitCafe as an app.

GitCafe-hosted runners

GitCafe's own hosted runners (ubuntu-latest, ubuntu-24.04, ubuntu-22.04) are started by GitCafe's fleet. The protocol the fleet uses to learn about queued jobs is internal to GitCafe and closed to third parties; you don't need to do anything to use hosted runners.

Third-party runner services

Services that run GitHub Actions jobs on their own machines connect to GitHub, not to GitCafe:

  • Depot, Namespace and hosted Ubicloud serve github.com only.
  • Blacksmith, WarpBuild and others that support GitHub Enterprise Server could serve GitCafe.

A runner service can serve GitCafe by publishing a GitCafe app that your organization installs; see Build a runner service as an app. None is available today. Until then, a workflow whose runs-on names such a service's labels waits for a runner until its run times out. Change runs-on to ubuntu-latest or to your own self-hosted runners.

Autoscalers you run yourself

actions-runner-controller (ARC) with runner scale sets, terraform-aws-github-runner and RunsOn need GitHub's scale-set and webhook APIs, which GitCafe doesn't offer yet; they don't work with GitCafe.

To start a fresh machine for each job with your own tooling, use ephemeral or just-in-time runners: your script asks GitCafe for a JIT configuration, starts a machine with it, and the runner unregisters itself after one job.

Build a runner service as an app

A runner service publishes one GitCafe app; each organization that installs it lets it start just-in-time runners in that organization's runner groups. Its runners are GitHub's official runner, as on GitHub Enterprise Server.

  1. In the app's manifest, ask for the Runners permission ({ "kind": "org", "family": "runners", "level": "write" } in permissions.autonomous.scopes) and subscribe the app's webhook to actions.workflow_job. Read is enough for the events and the demand read below; Write also starts runners. Both levels are Org-wide and Owner only: the events and the demand name every repository the organization's runner groups serve, private ones and ones outside an installation's selected repositories included, and the runners take jobs, with their secrets, from all of them. An organization admin's API token with the same permission works the same way.

  2. The organization installs the app, on all repositories so its webhook hears about every job (app webhooks send events only from the repositories an installation can reach).

  3. Start runners for queued jobs: actions.workflow_job sends queued when a job one of the organization's runner groups serves is queued, with the job's labels and, when only one group serves it, its runnerGroupId. If you serve those labels, mint a runner with an installation token:

    sh
    1curl -X POST https://git.cafe/api/v3/orgs/acme/actions/runners/generate-jitconfig \
    2 -H "Authorization: Bearer $INSTALLATION_TOKEN" -H "Content-Type: application/json" \
    3 -d '{"name": "depot-7f3a", "runner_group_id": 12, "labels": ["depot-ubuntu-24.04"]}'

    Start a fresh machine with ./run.sh --jitconfig <encoded_jit_config>. The runner is ephemeral: it takes one job and unregisters itself. When runnerGroupId is null, several groups serve the job: use the group the organization chose while setting your app up (cafe runner groups list shows each group's number and pool ID).

  4. Follow the job through its events: in_progress when a runner takes it, with the pool and runner, and completed when it ends, or when it is cancelled before any runner took it. See Actions job events.

  5. Catch up after missed deliveries with the pool's demand: the Read pool demand operation of the REST API, with the pool ID as pool and the same installation token. The answer lists the pool's oldest queued jobs with their repository and labels and carries an ETag; send it back as If-None-Match with wait=<seconds> (up to 50) to hold the request until the demand changes. A pool of another organization, or one the token cannot read, answers 404.

An app reaches only its installing organization's own pools: never the GitCafe-hosted pool, another organization's pools or repository-level runners. Registration tokens and listing or removing runners still need an organization admin.

Read as MarkdownGitCafe documentation
Documentation