fix(install): stamp the bootstrap-complete marker from install.sh too

install.ps1 wrote the marker on Windows and the Rust installer now writes it,
but install.sh -- the path every Mac and Linux CLI install takes -- never did.
A machine set up with install.sh therefore looked uninstalled to the desktop
app, which re-ran first-run bootstrap on every launch.

Stamp the same schema-v1 payload install.ps1 writes, from both the staged
`complete` stage and monolithic main(). An unresolvable HEAD skips the marker
rather than writing one the desktop validator rejects: absent reads as a clean
"bootstrap needed", malformed reads as a confusing half-state.
This commit is contained in:
Brooklyn Nicholson 2026-07-26 16:06:50 -05:00
parent ea3be4191e
commit 2b0b5e4c53
2 changed files with 154 additions and 0 deletions

View file

@ -2391,6 +2391,48 @@ maybe_start_gateway() {
fi
}
write_bootstrap_marker() {
# Writes $INSTALL_DIR/.hermes-bootstrap-complete, which tells the Hermes
# desktop app (apps/desktop/electron/main.ts) and the macOS launcher fast
# path (apps/bootstrap-installer) "a real install finished here -- don't
# re-run first-run bootstrap."
#
# Schema mirrors install.ps1's Write-BootstrapMarker and main.ts's
# writeBootstrapMarker(). Keep the three in lockstep:
# schemaVersion 1 + pinnedCommit (length >= 7) are what the desktop
# validator requires; desktopVersion is omitted because only the desktop
# app knows its own version.
if [ ! -d "$INSTALL_DIR" ]; then
log_warn "Skipping bootstrap marker: $INSTALL_DIR doesn't exist"
return 0
fi
# Explicit --commit wins; otherwise read HEAD from the checkout we just
# installed. If neither resolves, skip the marker entirely rather than
# write one the desktop will reject -- an absent marker is a clean
# "bootstrap needed", a malformed one is a confusing half-state.
local pinned_commit="$INSTALL_COMMIT"
if [ -z "$pinned_commit" ]; then
pinned_commit=$(git -C "$INSTALL_DIR" rev-parse HEAD 2>/dev/null) || pinned_commit=""
fi
if [ -z "$pinned_commit" ]; then
log_warn "Skipping bootstrap marker: could not resolve HEAD in $INSTALL_DIR"
return 0
fi
local marker_path="$INSTALL_DIR/.hermes-bootstrap-complete"
local tmp_path="$marker_path.tmp"
# Atomic publish: the macOS launcher predicate only checks existence, so a
# torn write would arm the fast path against a half-written marker.
printf '{\n "schemaVersion": 1,\n "pinnedCommit": "%s",\n "pinnedBranch": "%s",\n "completedAt": "%s"\n}\n' \
"$pinned_commit" \
"$BRANCH" \
"$(date -u +%Y-%m-%dT%H:%M:%S.000Z)" > "$tmp_path"
mv -f "$tmp_path" "$marker_path"
}
print_success() {
echo ""
echo -e "${GREEN}${BOLD}"
@ -3024,6 +3066,7 @@ run_stage_body() {
detect_os
resolve_install_layout
print_success
write_bootstrap_marker
# Code-scoped stamp: write next to the install tree, not into
# $HERMES_HOME. $HERMES_HOME is a shared data dir (it can be
# bind-mounted into a Docker gateway too), so a stamp there gets
@ -3108,6 +3151,8 @@ main() {
print_success
write_bootstrap_marker
# Code-scoped stamp: write next to the install tree, not into $HERMES_HOME.
# $HERMES_HOME is a shared data dir (it can be bind-mounted into a Docker
# gateway too), so a stamp there gets clobbered by the container's 'docker'