ushr

module
v0.2.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 27, 2026 License: Apache-2.0

README

ushr

Cross-org priority scheduler for self-hosted GitHub Actions runners. Architecture in DESIGN.md.

Status: v0.2.6, Apache-2.0. Multi-host, keyless: the agent holds your GitHub App key and the control plane never sees a credential.

Run it two ways. Self-host the controller alongside the agent (ushr setup) and nothing leaves your network. Or point the agent at the hosted control plane at ushr.io (ushr login) for cross-machine scheduling and a dashboard — the key still never leaves your box.

Components

Binary Role
ushr User-facing CLI. ushr login sets a host up end to end for the hosted plane; ushr setup --org NAME creates the GitHub App and records it in agent.yaml; ushr doctor checks host health; ushr init [dir] rewrites a repo's workflow runs-on targets to ushr labels.
ushr-controller Schedules queued jobs across agents over a long-poll HTTP API (keyless: agents report metadata, the controller holds no GitHub credentials)
ushr-agent Runs on the runner host. Holds the GitHub App keys, watches GitHub for queued jobs, mints JIT configs, and uses the configured Driver (Tart on macOS, docker/podman on Linux) to provision/destroy ephemeral runners

Quick start — one command per host

Install the binaries:

curl -fsSL https://get.ushr.io | sh
# or, from a checkout: ./deploy/install.sh

Then, on the runner host:

# Hosted plane (ushr.io): guided end-to-end setup —
# config, prereq installs (tart / podman, runner image), browser
# enrollment, GitHub App creation, service install + start.
ushr login

# Local/OSS single host, no account: GitHub App + local
# controller/agent services.
ushr setup --org YOUR_ORG

Both are interactive but zero-edit: prereqs are offered as guided installs (brew install tart, image pulls, podman), the GitHub App flow is two browser clicks, and the org block is written into ~/.config/ushr/agent.yaml for you. On Linux the per-repo docker build cache is on by default.

Check a host any time:

ushr doctor

Managed agent updates

Workspace admins can select Update agent on a host in the Fleet dashboard. The host finishes active jobs before it installs the latest stable agent release. It downloads the official release and verifies GitHub's archive checksum. A supervisor restores the previous agent if the new process cannot contact the control plane within 90 seconds. The dashboard shows the installed version, update progress, and failures.

Existing hosts need one manual installation of v0.2.5 to enable this feature. Managed updates replace the agent binary. Use the installer to update the CLI and a local controller.

Development

make build          # bin/ushr, bin/ushr-controller, bin/ushr-agent
make test           # go test ./...
make lint           # golangci-lint run

End-to-end Tart driver smoke (requires real Tart + an org with the App installed):

go run ./cmd/integration-test -trigger-repo=example-repo

Note: mints a real org-level runner registration in GitHub, dispatches a real workflow on -trigger-repo, and deletes both on success. Don't point at a production org for casual testing.

Roadmap

Shipped: Tart / Lume / Docker / SSH drivers, polling and scaleset sources, priority + aging, multi-host, two-phase keyless dispatch, per-agent enrollment, persistent dispatch ledger, ushr cost, one-command host setup, disk-pressure gating and reclaim.

Next: Kubernetes driver, Prometheus metrics, docs site.

Auth model

  • Controller ↔ Agent: per-agent enrollment tokens minted by ushr login, scoped to the orgs the agent may serve. Self-hosted single-host instead uses a shared bearer token, or no token at all when bound to loopback.
  • Agent ↔ GitHub: GitHub App per org via ghinstallation/v2. App ID + private key path in agent.yaml; installation ID auto-discovered. The control plane never sees a GitHub credential.
  • JIT runner registration: the agent mints a fresh JIT config per dispatch via Actions.GenerateOrgJITConfig. Runner is single-use and self-removes from GitHub when the job finishes.

License

Apache-2.0.

Directories

Path Synopsis
cmd
agent command
controller command
integration-test command
Command integration-test exercises the Tart driver end-to-end against a real paddo-runner-mac image.
Command integration-test exercises the Tart driver end-to-end against a real paddo-runner-mac image.
ushr command
Command ushr is the user-facing CLI.
Command ushr is the user-facing CLI.
internal
agent
Package agent runs the long-poll loop on the runner host.
Package agent runs the long-poll loop on the runner host.
api
Package api defines the control-plane<->agent HTTP protocol.
Package api defines the control-plane<->agent HTTP protocol.
disk
Package disk reports free space on a runner host's image store.
Package disk reports free space on a runner host's image store.
dispatch
Package dispatch is the controller's persistent record of in-flight dispatches.
Package dispatch is the controller's persistent record of in-flight dispatches.
dispatch/pg
Package pg is a Postgres-backed dispatch.Store for the hosted control plane.
Package pg is a Postgres-backed dispatch.Store for the hosted control plane.
domain
Package domain holds neutral types shared across components.
Package domain holds neutral types shared across components.
driver/docker
Package docker implements the Driver interface by running each ephemeral runner as a container via the Docker or Podman CLI (autodetected, or pinned via Options.Runtime — the two are drop-in for the subcommands used here).
Package docker implements the Driver interface by running each ephemeral runner as a container via the Docker or Podman CLI (autodetected, or pinned via Options.Runtime — the two are drop-in for the subcommands used here).
driver/factory
Package factory builds a Driver from agent config.
Package factory builds a Driver from agent config.
driver/lume
Package lume binds the lume CLI (MIT, Apple Virtualization.framework) to the generic VM driver in internal/driver/vmdriver.
Package lume binds the lume CLI (MIT, Apple Virtualization.framework) to the generic VM driver in internal/driver/vmdriver.
driver/sshrunner
Package sshrunner holds the SSH-based runner bootstrap shared by the macOS drivers (tart, lume).
Package sshrunner holds the SSH-based runner bootstrap shared by the macOS drivers (tart, lume).
driver/tart
Package tart binds the tart CLI (Apple Virtualization.framework) to the generic VM driver in internal/driver/vmdriver.
Package tart binds the tart CLI (Apple Virtualization.framework) to the generic VM driver in internal/driver/vmdriver.
driver/vmdriver
Package vmdriver provides a generic ephemeral-VM Driver shared by the macOS drivers (tart, lume).
Package vmdriver provides a generic ephemeral-VM Driver shared by the macOS drivers (tart, lume).
enroll
Package enroll handles agent authentication for the hosted control plane: per-agent enrollment tokens (validated against Neon) and the browser-session + PKCE handshake behind `ushr login`.
Package enroll handles agent authentication for the hosted control plane: per-agent enrollment tokens (validated against Neon) and the browser-session + PKCE handshake behind `ushr login`.
jit
Package jit mints GitHub Actions runner JIT configs per org installation.
Package jit mints GitHub Actions runner JIT configs per org installation.
ledger
Package ledger is an append-only store of completed ushr jobs.
Package ledger is an append-only store of completed ushr jobs.
source/github
Package github implements a polling Source backed by the GitHub Actions API.
Package github implements a polling Source backed by the GitHub Actions API.
source/scaleset
Package scaleset implements a Source backed by GitHub's Runner Scale Set API (the mechanism behind actions-runner-controller, via the standalone actions/scaleset client).
Package scaleset implements a Source backed by GitHub's Runner Scale Set API (the mechanism behind actions-runner-controller, via the standalone actions/scaleset client).
svc
Package svc installs and controls the ushr launchd/systemd user services, so the CLI can take a host from enrolled to running without a repo checkout or hand-run launchctl/systemctl incantations.
Package svc installs and controls the ushr launchd/systemd user services, so the CLI can take a host from enrolled to running without a repo checkout or hand-run launchctl/systemctl incantations.
telemetry
Package telemetry persists the dispatch story the control plane otherwise drops: finished jobs (job_runs), agent liveness (agent_status), and a live transition feed (dispatch_events).
Package telemetry persists the dispatch story the control plane otherwise drops: finished jobs (job_runs), agent liveness (agent_status), and a live transition feed (dispatch_events).
update
Package update installs official agent releases after the host drains.
Package update installs official agent releases after the host drains.
webhook
Package webhook receives GitHub workflow_job events and feeds completed jobs run on ushr runners into the ledger.
Package webhook receives GitHub workflow_job events and feeds completed jobs run on ushr runners into the ledger.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL