Skip to content

CI Runners

Shiplight runners are an alternative to GitHub-hosted runners like ubuntu-latest. They are ephemeral VMs that register themselves with GitHub as standard self-hosted runners, run exactly one job, and are then destroyed.

They are not a separate CI system. Your workflow files stay as they are — the only line that changes is runs-on. This page covers the cloud side: enabling runners, choosing a size, managing pools, and debugging dispatches. For writing the workflow itself, see GitHub Actions.

Why use them

GitHub-hosted ubuntu-latestShiplight runner
BrowsersYou run npx playwright installChromium, Firefox, and WebKit prebaked
Shiplight credentialsYou store SHIPLIGHT_API_TOKEN as a secretInjected per run, revoked when the run ends
LLM credentialsYou supply your own provider keyLLM proxy credentials injected by default — your own key still works
Result uploadYou set SHIPLIGHT_REPORT_TO_CLOUD=1Enabled by the platform
Machine sizeFixed4, 8, 16, or 32 vCPU

Setup

1. Install the GitHub App

An org owner installs the Shiplight GitHub App from Settings → Integrations → Connect GitHub at app.shiplight.ai/settings/integrations. The consent screen requests:

PermissionLevelWhy
ActionsRead-onlyReceive workflow_job events
Self-hosted runners (organization)Read and writeMint runner registration tokens
MetadataRead-onlyBasic repository data
ContentsRead-onlyCheck out your code
Pull requestsRead-onlyAssociate runs with PRs
ChecksRead and writeReport status back

The App also subscribes to the Workflow job webhook event.

The repository must be owned by a GitHub organization

Runner registration tokens are minted at the organization level. Repositories under a personal GitHub account cannot use Shiplight runners. The job sits queued in GitHub indefinitely and nothing is recorded under Dispatches, which makes this the most common — and least obvious — setup trap.

2. Connect the repository

The repository must appear as an active connected repo under Settings → Integrations. If you install the App but exclude a repository from its repository selection, that repo's jobs are never run — the dispatch is closed as Cancelled by user, even though nobody cancelled it.

3. Enable runners for the org

An owner turns on the Shiplight runners toggle on the Pools tab at app.shiplight.ai/runners.

It is off by default, and only owners can change it. While it is off you are not charged: the job waits in GitHub's "Waiting for runner" state, and the dispatch is recorded under Organization not enabled.

Turning it off later does not kill running jobs; they finish, and only new queued events are ignored.

4. Point your workflow at a runner

yaml
jobs:
  e2e:
    runs-on: shiplight-medium

Runner sizes

runs-on labelvCPUMemory
shiplight-small416 GB
shiplight-medium832 GB
shiplight-large1664 GB
shiplight-xlarge32128 GB

Exactly one shiplight-* size label must be present on runs-on.

Managing pools

The Pools tab at app.shiplight.ai/runners lists one row per size, each with:

  • Enabled — whether that size can be provisioned at all
  • Min — runners kept provisioned (default 0)
  • Max — ceiling for that pool (default 5)

Only owners can edit pools, and changes apply on the next scaler tick. A pool that is disabled or has Max set to 0 provisions nothing, and matching jobs wait in GitHub indefinitely.

Limits

  • Total concurrent runs are capped, at 20 by default. Contact the Shiplight team to raise it if you need more.
  • Jobs are capped at 60 minutes by default, and killed with Time cap exceeded. A workflow declaring timeout-minutes: 90 is clamped to the ceiling — the higher value is not honored. Contact the Shiplight team if you need a longer ceiling.

Debugging a run

The Dispatches tab at app.shiplight.ai/runners is the first place to look when a job misbehaves — check it before escalating.

Filter by status (Queued / In Progress / Completed), repository, or date range. Each row shows status, repository, branch, start time, duration, and a link straight to the job on GitHub. Any row that isn't still queued expands to give you:

  • The failure reason, in plain language
  • An execution timeline of the GitHub Actions steps with per-step duration and outcome
  • The linked Shiplight Run #N, with pass/fail/flaky/skipped counts and a link to the run details

Failure reasons

Shown asWhat it means
Process exited with non-zero codeYour tests or a workflow step failed
Time cap exceededHit the time ceiling
Multiple size labels detectedMore than one shiplight-* label on runs-on
Unsupported size labelThe label is not a known size
Organization not enabledThe Shiplight runners toggle is off
Cancelled by userThe job was cancelled — or the repository is not connected, which closes the dispatch the same way
GitHub assigned job elsewhereGitHub gave the job to a different runner
Runner provisioning failedA platform-side failure — contact support

Job stays queued

Some conditions produce no dispatch record at all and simply leave the job waiting in GitHub. Work through these in order:

  1. The pool for that size is disabled, or its Max is 0.
  2. The org-wide concurrency cap is saturated.
  3. The repository is under a personal account rather than an organization.
  4. Your account balance is insufficient.

If instead you see a dispatch with a failure reason, use the table above — a disconnected repository and a disabled organization both record one.

Bringing your own runner

Shiplight does not ship an installable runner agent. If you want to run on your own hardware, use GitHub's own self-hosted runners and treat them like any non-Shiplight runner: supply SHIPLIGHT_API_TOKEN yourself and set SHIPLIGHT_REPORT_TO_CLOUD=1 to upload results. GitHub Actions documents that path.

Released under the MIT License.