Abdelrhman

Self-Hosted CI Controller
0 Views

Self-Hosted CI Controller

Open-source GitHub Actions controller that starts a Scaleway worker for queued jobs and stops it when idle.

Project Overview

Self-Hosted CI is an open-source controller for GitHub Actions jobs that need a self-hosted runner. Repository maintainers label a job for the worker; the controller starts a Scaleway instance when there is work and powers it off after an idle period.

The problem

A runner that remains powered on between jobs consumes compute even when a repository is quiet. A runner rebuilt from nothing for every job also loses the benefit of a retained machine and disk. This controller keeps the worker instance available as a stopped resource, starts it for queued jobs, and uses an ephemeral GitHub runner registration for each job.

Key features

  • Receives GitHub workflow_job webhooks and selects jobs with the required runner labels.
  • Verifies webhook signatures before changing queue state.
  • Suppresses duplicate queued jobs and stores controller state in a local JSON file.
  • Creates a Scaleway worker with cloud-init, or finds and reconciles an existing worker.
  • Starts the instance when the queue needs capacity and stops it after an idle interval.
  • Gives the worker a job through an authenticated internal endpoint and records completion through another.
  • Requests GitHub App installation and runner registration tokens for the target repository.
  • Exposes a health response with queue length, worker power state, and current work.

Technical architecture

A Node.js and Express controller listens on localhost. GitHub sends webhook events to its public route through the intended reverse proxy. The controller records jobs and worker metadata in data/state.json, written with restricted file permissions. It calls the Scaleway CLI to create, start, inspect, and stop the instance. Cloud-init installs the worker toolchain and a systemd polling loop. The worker requests its next job, registers an ephemeral GitHub Actions runner, runs the job, and reports completion. GitHub App authentication supplies short-lived tokens rather than a stored personal access token.

Engineering highlights

  • Both webhook HMACs and internal Bearer secrets use timing-safe comparisons.
  • The controller checks required configuration at startup and limits its listener to loopback.
  • Queue state survives controller restarts through the restricted local state file.
  • Worker reconciliation can adopt an already-created instance after a controller restart.
  • Idle shutdown is a power-state transition; the retained instance can be started for later jobs.

Image Gallery

No media available for this project.

Client Reviews

Feedback from people who used or collaborated on this project.

Share your experience with this project