`homeboy upgrade`
Synopsis
homeboy upgrade [OPTIONS]Description
Upgrades Homeboy to the latest version. The command auto-detects the installation method (Homebrew, source build, or downloaded release binary) and runs the appropriate upgrade process.
By default, after a successful local upgrade, Homeboy also converges configured SSH runners on the installed controller release. This keeps lab runners from drifting behind the local CLI.
GitHub authentication
Upgrade resolves credentials once per process: nonempty GH_TOKEN, then
GITHUB_TOKEN, then gh auth token --hostname github.com (up to five seconds).
If the CLI is missing, logged out, or fails, requests remain anonymous. Tokens
are sent only to https://api.github.com. Check and upgrade JSON report
token_source as env, gh_cli, or none. Rate-limit errors name the reset
time in RFC 3339 and recommend gh auth login or setting GH_TOKEN.
For binaries older than v0.448.2 affected by authenticated release selection,
use GH_TOKEN= homeboy upgrade (also unset GITHUB_TOKEN if set), or reinstall
with the install script. This historical escape hatch does not disable the
gh fallback in current binaries.
Runner convergence
Each selected SSH runner goes through the same runner-binary convergence as homeboy runner connect (see runner connection). The target is the controller identity the upgrade just installed, not the build of the process running the upgrade. Convergence compares the runner’s configured homeboy_path (its self identity) with that target and installs the target’s exact release tag through refresh-homeboy‘s verified release path only when the runner is older. It never downgrades, and it never replaces a daemon that has active jobs.
Outside an upgrade, homeboy runner connect <runner> runs this same convergence against the current controller, so it is the normal way to bring a single runner up to date. homeboy runner refresh-homeboy is for explicit refs (--ref), selecting an existing binary (--select), downgrades (--allow-downgrade), dev builds (runner dev-sync), and the manual fallback below when convergence failed.
Each convergence outcome maps onto the runner’s upgrade entry like this:
| Convergence status | Entry |
|---|---|
converged | success: true, upgraded: true, new_version is the target version |
already_current | success: true, upgraded: false; nothing is installed |
pending_active_jobs | deferred: true; detail names the blocking job IDs; recover with homeboy upgrade --upgrade-runner <runner> once they finish |
failed, skipped_unverifiable | success: false; detail keeps the attributed cause; recover with homeboy runner refresh-homeboy <runner> --ref v<target> --reconnect |
skipped_remote_newer, skipped_dev_build | success: false, with no recovery command (the runner is never downgraded, and a dev build has no published release) |
Only a converged or already_current binary continues to:
- sync every parent extension that has portable source metadata (
source_urlplussource_revision) to the runner, isolating failures per extension; - report a stale connected runner daemon (
stale_daemon) whose session version does not match the target; - reconcile the runner-service unit binaries (
service_binaries), restarting this controller’s stale unit through the idle-gatedrefresh-homeboy --reconnecthandoff.
Controller upgrades install the verified binary, stop the resident daemon by its exact lease, and start the installed binary in the same state directory. Startup recovery resumes in-flight work; upgrades do not drain, cancel, or block new Cook admission. A candidate with a different observation-store schema is refused while non-terminal work exists, naming that work and leaving all binaries unchanged.
Options
status [ID]: Inspect a persisted upgrade operation. Reports whether binary promotion and optional extension/runner refresh completed. OmitIDto read the latest upgrade run. Also available ashomeboy runs show <id>.--check: Check for updates without installing. Returns version information without making changes.--force: Force upgrade even if already at the latest version; does not cancel active work.--skip-extensions: Skip automatic extension updates.--skip-runners: Upgrade the controller only; cannot be combined with--upgrade-runner.--upgrade-runner: Select configured runners to converge with the controller upgrade. Repeat to target multiple runners.--runner-only: With--upgrade-runner, preserve the controller and refresh only the selected runners. The response explicitly reports this partial scope and the exact controller-plus-runner convergence command.--method: Override install method detection (homebrew|source|binary).--version <TAG>: Pin the published release to install (v0.332.0or0.332.0). When--methodis omitted, this infers--method binaryand reports that choice before mutation. An explicit incompatible method is rejected. A pin also implies--forceat the release gate so a deliberate downgrade is not discarded as "already at latest".
Release selection for binary installs
Binary installs download a release asset named homeboy-<target triple>.tar.xz, plus its .sha256 sidecar. A release published without this platform’s pair cannot be installed here, so upgrade does not simply resolve the newest tag:
--checkverifies an installable artifact, not just a newer version string.latest_versionis the newest release carrying an artifact for the running target, andupdate_availableis keyed off it. A release this platform cannot install is never reported as available.- Selection falls back to the newest release that does have this target’s asset, and says so:
v0.333.0 has no x86_64-unknown-linux-gnu asset; upgrading to v0.332.0 instead. --version <TAG>pins deliberately. With no explicit--method, a pin selects the binary install method even when the current controller was installed by Cargo. A pin to a release with no asset for this target is refused before any binary mutation, naming the asset it looked for and the releases that would work.- The target triple is detected honestly. An OS/architecture pair Homeboy publishes no assets for is reported as undetermined; asset availability is then explicitly not verified rather than guessed.
- A 404 names the resolved asset URL and the target triple it looked for, so diagnosing a missing asset does not require listing release assets by hand.
Binary upgrades run the same homeboy-installer.sh that is published as a release asset, with HOMEBOY_INSTALL_STAGE_ONLY=1 and HOMEBOY_INSTALL_PATH pointing into an isolated stage. In that mode the installer only downloads, checksum- and version-verifies, and places the candidate in the stage; Homeboy then verifies the staged candidate, queries its observation-store schema before replacement, and atomically promotes it over the active binary. The installer honors HOMEBOY_UPGRADE_RELEASE_TAG to download from a specific tag instead of releases/latest/download; upgrade sets it from the release it selected.
Controllers released before the bootstrap admission contract can recover without
running their legacy upgrade command by invoking the pinned release installer:
curl -fsSL https://github.com/Extra-Chill/homeboy/releases/download/v<fixed-version>/homeboy-installer.sh | shThe installer stages the candidate, has that candidate read durable ownership with the legacy controller identity, and only replaces the installed binary when the candidate admission succeeds.
Installation Method Detection
Homeboy detects how it was installed and uses the appropriate upgrade method:
| Method | Detection | Upgrade Command |
|---|---|---|
| Homebrew | Binary path contains /Cellar/ or /homebrew/, or brew list homeboy succeeds | brew update && brew upgrade homeboy |
| Source | Binary path contains /target/release/ or /target/debug/ | git pull && cargo build --release |
| Binary | Binary path contains /bin/homeboy (covers ~/bin/homeboy, /usr/local/bin/homeboy, and ~/.cargo/bin/homeboy) | Runs homeboy-installer.sh in stage-only mode, then verifies, admits, and promotes the staged release over the current binary |
If the installation method cannot be detected, an error is returned with manual upgrade instructions. You can also override detection:
homeboy upgrade --method binaryExamples
Check for updates:
homeboy upgrade --checkUpgrade to the latest version:
homeboy upgradeForce reinstall:
homeboy upgrade --forcePin a specific published release (infers a binary install):
homeboy upgrade --version v0.332.0Upgrade only a specific runner after the local upgrade:
homeboy upgrade --upgrade-runner labUpgrade locally without touching configured runners:
homeboy upgrade --skip-runnersJSON output
Note: all command output is wrapped in the global JSON envelope described in the JSON output contract.
Note: all command output is wrapped in the global JSON envelope described in the JSON output contract.
command:upgrade.checkcurrent_version: Current installed versionlatest_version: The release an upgrade would install. For asset-installed methods this is the newest release carrying an artifact fortarget. Null when the network check failed, or when no published release ships this target’s artifactupdate_available: Boolean indicating if an installable update is availableinstall_method: Detected installation method (homebrew,binary,source, orunknown)target: Running target triple. Omitted when the OS/architecture pair could not be identified, which means asset availability was not verifiednewest_version: Newest published release, whatever its asset inventory. Equal tolatest_versionon a healthy release trainuninstallable_versions: Releases newer thanlatest_versionpassed over for want of atargetasset, newest firstnotice: Plain-language explanation whenlatest_versionis not the newest release, when nothing installable was found, or when the target could not be determined
Note: all command output is wrapped in the global JSON envelope described in the JSON output contract.
command:upgrade.statusoperation_id: Persisted observation-run idstatus: Observation run status (running,pass,error, …)phase: Current or terminal upgrade phaseelapsed_seconds: Bounded elapsed time for the recorded phasecontroller/extensions/runners: Independent component statusesnote: Present when a running record’s owner process is no longer alive
homeboy upgrade --check data payload:
homeboy upgrade status [ID] data payload:
command:upgradeoperation_id: Durable observation-run id persisted before mutation. Inspect later withhomeboy upgrade status <id>install_method: Installation method used for upgradeprevious_version: Version before upgradenew_version: Version after upgrade (may be null)upgraded: Boolean indicating if upgrade was performedpartial: Present and true when a selected runner did not converge with the controllerrunners_deferred: Busy runners whose opportunistic refresh was deferredmessage: Human-readable status messagerestart_required: Boolean indicating if a restart is needed (true only for source installs)extensions_updated: Extension upgrade entries when installed extensions were checkedextensions_skipped: Extension IDs that could not be updatedprojects_migrated: Project config migration entriesrunners_updated: Runner upgrade entries for configured runners that completed successfullyrunners_skipped: Runner upgrade entries for configured runners that failed or could not verify a version
Status reads reconcile an upgrade record whose owner has exited to
a non-success interrupted terminal state, projecting any pending binary
replacement from its durable checkpoint. A proven controller replacement
remains visible independently from incomplete extension or runner refresh.
Controller replacement does not wait for live runtime-generation pins.
Upgrades run in the foreground through binary promotion and daemon restart
resumption. A queued worker is not reported as successful completion. Only the
controller admission window is fenced while existing Cooks finish. Runner jobs
keep running and later complete through the upgraded controller. After the
controller upgrade, each selected runner converges on the installed release:
idle runners converge at once, and runners whose daemon has active jobs go in
runners_deferred with runner busy: the daemon has active jobs (<job-ids>); ....
Deferred runners do not make the upgrade partial.
Exit code
0: Completed upgrade with selected targets converged and runner admission restored.- Non-zero: Schema-change refusal, preflight failure, partial upgrade, failed component, interrupted operation, pending service restart, or admission-readiness failure.
Notes
- Version checking queries the GitHub Releases API. Network failures are handled gracefully.
- On Unix platforms, successful source installs automatically restart into the new binary. Binary and package-manager installs do not require a restart.
- Upgrade persists a durable operation before controller mutation. Long extension refresh emits bounded
[upgrade] phase=... elapsed=Nsheartbeats.homeboy upgrade statusreconciles dead foreground owners and reports whether the destination hash matches the selected release’s durably recorded sha256; optional refresh is marked interrupted when its owner exits.