Skip to content
GantryCD

GitHub Actions

At a glance — the backend-dispatched, zero-infrastructure option. GantryCD calls workflow_dispatch in your repo for each run, and the workflow drives the rest of the protocol. There’s no launcher process for you to host.

Configure

Set up once:

  1. Create a GitHub App and install it on the repo you’ll dispatch to. Note its App ID and generate a private key (.pem) — you’ll register both on the runner group. Grant exactly one permission: Actions: Read and write.
  2. Commit the runner workflow to .github/workflows/gantrycd-runner.yaml — copy it verbatim from the Workflow template. It pins the runner action and needs no edits across GantryCD upgrades, but it must declare all three workflow_dispatch inputs the dispatcher sends — assignment-token, gantrycd-url, and correlation-id — and echo the last into the run name as run-name: gantrycd-${{ inputs.correlation-id }}. A workflow missing correlation-id is rejected by GitHub on every dispatch — see Troubleshooting.
  3. Create a github-actions runner group (under Org settings → Runner groups) pointing at the repo, the workflow file, and the App’s ID + private key. The signing keypair the runner uses is generated and held by GantryCD — you never see it.

Permissions

The runner group needs one fine-grained repository permission on its GitHub App:

PermissionAccessUsed for
ActionsRead and writeRead to track and re-discover dispatched runs; write to call workflow_dispatch.

You can reuse your source-control GitHub App — just add Actions: Read and write to it — or use a dedicated App. Either way, register the App ID + private key on the runner group itself: runner-group credentials are stored separately from the SCM integration’s, even when it’s literally the same App.

A launcher driving this from outside the backend uses these env vars:

VariableRequiredNotes
GITHUB_TOKENYestoken used to dispatch workflows
GITHUB_OWNERYesowner / org
GITHUB_REPOYesrepository name
GITHUB_WORKFLOW_FILENoworkflow filename; defaults to gantrycd-runner.yaml
GITHUB_API_URLNohttps://api.github.com

How it behaves

  • GantryCD holds the runner signing key server-side (you never see it), mints a per-run token, and calls workflow_dispatch. The workflow reads the GantryCD URL from the dispatch input, so the same file survives backend URL changes.
  • The group shows connected while GantryCD’s dispatcher is healthy.

Note: these runners run off your network. Point GantryCD’s storage at a publicly reachable endpoint so they can upload state and logs — see Storage.

Run a prebuilt binary

There’s a workflow template that downloads a prebuilt runner from a tagged gantrycd release, installs tenv, and runs the binary directly. See Workflow template: prebuilt binary.

Troubleshooting

Dispatch fails with 422 Unexpected inputs provided (GitHub reports correlation-id as an unexpected input). Your committed workflow predates the correlation-id input. GantryCD sends correlation-id — an opaque <group-id>/<run-id> — on every workflow_dispatch, so the workflow has to declare it as an input (alongside assignment-token and gantrycd-url) or GitHub rejects the call before the run ever starts.

correlation-id is how GantryCD finds the run it started: the list-runs API returns a run’s run-name but not its dispatch inputs, so the workflow surfaces it via run-name: gantrycd-${{ inputs.correlation-id }}. That run-name lets the dispatcher both poll a run to completion and re-discover in-flight runs after a backend restart — which is what makes restarting the backend safe (it re-attaches to runs already in progress instead of orphaning them). The runner action itself never reads correlation-id; it exists purely for this correlation.

Fix: re-copy the current Workflow template (or the prebuilt-binary variant). Both declare all three inputs and set run-name.

Internals

The dispatcher loop, the workflow template, and the App setup are in GitHub-Actions runner groups.