Skip to main content
CI on Zode runs a GitHub Actions job in a fresh sandbox, one sandbox per job, deleted when the job ends. You pay for the runner’s compute from creation to deletion.

Set it up

  1. An owner or admin opens the console, Configure, CI, and clicks Install on GitHub. Installation happens in the console only; there is no CLI or API-key flow for it.
  2. On GitHub, pick the account and repositories. GitHub sends you back to the console, which links the installation to your workspace. One installation belongs to one workspace.
  3. In a workflow, set runs-on to a Zode label:
The Zode GitHub App asks for these repository permissions: Administration (read and write, used only to register and remove just-in-time runners), Actions (read) and Metadata (read).

Runner sizes

self-hosted, linux and x64 may appear next to a Zode label. Any other label, an unknown size, or two different Zode sizes in one runs-on gets the job refused with a reason. Jobs without a Zode label are ignored: not recorded, not billed.

How a job runs

  1. GitHub reports the job queued. Zode records it and checks the monthly cap.
  2. Zode registers a just-in-time runner on the repository, creates a sandbox of that size (audited as sandbox.create by ci:github) and starts the runner in it.
  3. The job runs. When GitHub reports it completed, Zode records the conclusion and deletes the sandbox.
Every runner boots the ci-ubuntu-24.04 official image, which lists the software it has. A repository that ran a job in the last 30 minutes keeps a standby runner ready, so the next job does not wait for a machine. With warm snapshots on, cache_hit says whether the job started from the last green default-branch job’s disk. A runner that lives longer than 6 hours is deleted. To move a workflow, see Move a workflow to Zode. For results, sharding and selection, wrap the test command in zode-ci test.

Monthly cap

Owners and admins set a cap on CI spend per UTC calendar month. null removes it.
Past the cap, new jobs are refused with the reason “monthly CI cap reached: XofX of Y spent”. Running jobs finish. Each refusal is audited as ci.job_refused. CI sandboxes are ordinary sandboxes, so the workspace daily cap also applies to them.

See jobs and spend

GET /v1/ci (every role) returns whether CI is configured, the runner sizes, your GitHub installations with their repositories, the monthly cap and this month’s spend:
GET /v1/ci/jobs?limit=50 (1 to 200) lists jobs newest first:
cost_final: false means the runner is still live and cost_micros is the cost so far. Job cost counts compute only; the runner’s short-lived disk is not charged. If you uninstall the app on GitHub, Zode unlinks it and frees any live runner sandboxes. While the app is suspended on GitHub, new jobs are refused.