Skip to content

installer: build the builder image on Linux and on release installs - #393

Open
mpuig wants to merge 5 commits into
kernel:mainfrom
mpuig:fix/installer-builder-image
Open

installer: build the builder image on Linux and on release installs#393
mpuig wants to merge 5 commits into
kernel:mainfrom
mpuig:fix/installer-builder-image

Conversation

@mpuig

@mpuig mpuig commented Aug 11, 2026

Copy link
Copy Markdown

Problem

Source-to-image builds boot builder VMs from hypeman/builder:latest, and the API's fallback for installed (non-source) services is to find that image in the local Docker daemon — lib/builds/manager.go's own comment says "the installer builds this image before loading the service". But the installer only does that in its darwin branch, and only for source (BRANCH) installs.

A Linux release install therefore has no builder image and no way to grow one: ensureBuilderImage finds no source checkout (go.mod absent) and no local hypeman/builder:latest, preparation retries forever, and every hypeman build fails. On v0.3.0 the failure is especially opaque — the ready flag is set in a defer even on failure, so builds proceed and die with create builder instance: image is required.

Reproduced on a GitHub-hosted ubuntu runner installing v0.3.0 via get.hypeman.sh.

Fix

The builder-image step now runs on every platform where Docker is present:

  • source installs keep using the existing checkout in TMP_DIR;
  • release installs fetch the source tarball for the exact installed $VERSION and build from it — the builder Dockerfile is part of the same tree the binaries were released from;
  • skipped when hypeman/builder:latest already exists; warn-and-continue when it cannot be built (matching the existing style).

On Linux the service is already running by this point; the startup preparation loop picks the image up on its next retry. On macOS the ordering (build before service load) is unchanged.

Testing

  • bash -n clean.
  • The equivalent sequence (fetch pinned source → docker build -t hypeman/builder:latest -f lib/builds/images/generic/Dockerfile) is what we run in barista's CI as a workaround, and it takes a fresh ubuntu runner from "every build fails" to green source-to-image builds.

Found while building barista on hypeman. An alternative worth considering: publish a pinnable pre-built builder image and default build.builder_image to it, which would remove the Docker dependency from installs entirely.


Note

Medium Risk
Install-time behavior changes for every Docker-backed install path (network fetch, privileged docker, longer installs); failures are non-fatal but source builds stay broken until the image is built manually.

Overview
Fixes broken hypeman build on Linux release installs by building hypeman/builder:latest during install whenever Docker is available, not only on macOS source installs.

The installer now skips if the image already exists, uses $SUDO docker when the user cannot talk to the daemon directly, and for tagged release installs downloads the matching GitHub source tarball so it can run docker build against lib/builds/images/generic/Dockerfile. Failed builds surface captured docker build output instead of hiding it; missing Docker or source still warns and continues like before.

On Linux the service may already be running when the image appears; the API’s builder-prep retry loop can pick it up. macOS still builds before launchctl load.

Reviewed by Cursor Bugbot for commit 94163c8. Bugbot is set up for automated code reviews on this repo. Configure here.

Source-to-image builds boot builder VMs from hypeman/builder:latest, and
the API's fallback for installed (non-source) services is to find that
image in the local Docker daemon -- lib/builds/manager.go's own comment
says "the installer builds this image before loading the service". The
installer only did so in its darwin branch, and only for source (BRANCH)
installs. A Linux release install therefore had no builder image and no
way to grow one: builder preparation retried forever, and every
`hypeman build` failed.

The builder-image step now runs on every platform where Docker is present,
and release installs fetch the source tarball for the exact installed
version to build from -- the builder Dockerfile is part of the same tree
the binaries were released from. Skipped when the image already exists,
warn-and-continue (matching the existing style) when it cannot be built.
Comment thread scripts/install.sh
Bugbot's review finding, and it is right: the script's documented Linux
invocation elevates privileged operations through $SUDO, but the new
builder-image step ran docker as the invoking user -- who may not be in the
docker group -- so the step would warn-and-skip and leave exactly the gap
this PR fixes. Docker access is now probed and escalated through the same
$SUDO the rest of the script uses.

Also stop discarding the docker build output: it goes to a log file whose
path the failure warning names, instead of 2>/dev/null-ing the only
evidence of why a build failed.
@mpuig

mpuig commented Aug 11, 2026

Copy link
Copy Markdown
Author

Good catch from Bugbot — fixed in b651481: docker access is now probed and escalated through the same $SUDO the rest of the script uses for privileged operations, so a non-docker-group invoking user on Linux still gets the image built. Also stopped discarding the docker build output — it now lands in a log file whose path the failure warning names, instead of 2>/dev/null-ing the only evidence of why a build failed.

Comment thread scripts/install.sh Outdated
@chruffins
chruffins self-requested a review August 11, 2026 21:17

@chruffins chruffins left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hey, thanks for submitting a PR for this! besides the bugbot finding which should be fixed, everything else looks good to me.

Comment thread scripts/install.sh Outdated
…log path

The builder-image build log lives under TMP_DIR, which the EXIT trap
removes when the script finishes, so the path named in the warning was
gone by the time anyone read it. Print the captured docker build output
to stderr on failure, before cleanup runs (per review feedback).
Comment thread scripts/install.sh
# TMP_DIR is removed by the EXIT trap, so print the captured output
# now rather than naming a log path that will not survive the install.
warn "Failed to build builder image; docker build output follows:"
sed 's/^/ /' "$BUILDER_BUILD_LOG" >&2

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Build log dumped to wrong stream

Low Severity

The failure path announces that docker build output follows via warn (stdout), then prints the log with sed on stderr. Every other user-facing message and build-log dump in install.sh uses stdout, so the log can appear detached from the warning—or vanish entirely when stderr is discarded—undermining the print-before-cleanup fix.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 42cbab4. Configure here.

@chruffins chruffins left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for putting this in!

@chruffins

Copy link
Copy Markdown
Contributor

/test

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 94163c8. Configure here.

Comment thread scripts/install.sh
if [ -n "$SUDO" ] && $SUDO docker info >/dev/null 2>&1; then
DOCKER="$SUDO docker"
fi
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Build continues after Docker probes fail

Low Severity

When both docker info and $SUDO docker info fail, DOCKER stays set to docker and the script still enters the build path. For release installs that means fetching the version source tarball before docker build fails for the same unreachable daemon, instead of skipping early with a clear accessibility warning.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 94163c8. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants