How It Works¶
End-to-end flow¶
queued workflow_job
-> controller receives event or poll result
-> state entry created to deduplicate the job
-> label selects image and sizing profile
-> Jeballto health check
-> create VM
-> start VM
-> wait for RUNNING
-> enable SSH
-> wait for SSH
-> verify runner files exist
-> request JIT runner config from GitHub
-> launch runner inside VM
-> verify runner is online
-> wait for completion
-> disable SSH, delete VM, remove runner, clear state
Event sources¶
Poll mode¶
The controller periodically lists queued workflow_job records for one repository. It also re-checks active jobs so cleanup still happens even without webhook delivery.
Webhook mode¶
The controller exposes /webhook and validates the workflow_job payload signature with github.webhook_secret.
Both mode¶
Both sources can observe the same job. The state store prevents duplicate provisioning.
Provisioning pipeline¶
The controller performs these major steps:
- verify the Jeballto Agent is healthy
- create the VM from the configured OCI image
- if the selected label overrides CPU, memory, or disk, patch those resources before start
- start the VM and wait for
RUNNING - enable SSH and wait for readiness
- probe for
run.sh,config.sh,bash, andgit - obtain a JIT runner configuration from GitHub
- start the runner inside the VM
- verify the runner shows as online
If JIT configuration is not supported, the controller falls back to registration-token mode and still verifies that the runner appears online.
Completion handling¶
When the job reaches completed, the controller:
- disables SSH forwarding
- force-deletes the VM
- removes the GitHub runner if it knows the runner ID
- deletes the local state record
VMs are also created with ephemeral: true, so the agent can auto-delete them after stop or error as a safety net. Controller-driven cleanup is still the primary teardown path while a VM is running.
Garbage collection¶
GC catches misses caused by:
- controller restart
- lost webhook delivery
- incomplete local state cleanup
It periodically scans for stale state and idle VMs, then cleans them up according to the configured thresholds.
Important code areas¶
internal/controller/controller.goties together modes, workers, and cleanupinternal/controller/poller.gohandles poll-mode detection and completion checksinternal/github/webhook.govalidates and parses webhook eventsinternal/config/config.govalidates mode-specific settingsinternal/ssh/runner.gostarts the guest runner process