fix(installer): never brick the install when a self-update swap fails - #38402
Merged
kshitijk4poor merged 1 commit intoJun 3, 2026
Merged
Conversation
The macOS self-update bundle swap (install_macos_app_update, added in NousResearch#38296) could leave the user with NO app installed. If moving the existing /Applications/Hermes.app aside failed, the code deleted the running app outright and set moved_old=false; if the subsequent move of the freshly built bundle into place then also failed, the rollback was gated on moved_old (now false) and skipped — leaving the target deleted with no replacement. Extract the swap into swap_in_new_bundle() with a strict invariant: on ANY failure path the target is left pointing at a working bundle (either the original, rolled back, or untouched) and is never deleted with no replacement. Also clean up the staged .hermes-update-new copy on the failure paths instead of orphaning it. Add unit tests covering the happy path, the rollback-on-install-failure path, and the catastrophic both-moves-fail path. The catastrophic-path test was verified to FAIL against the old code ("original app must NOT be deleted on failure") and pass against the fix.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up to #38296. The macOS self-update bundle swap (
install_macos_app_update) has a failure path that can leave the user with no app installed at all.The bug
In the swap sequence:
If moving the existing
/Applications/Hermes.appaside fails, the code deletestarget_appand setsmoved_old = false. If the subsequent move of the freshly built bundle into place then also fails, the rollback is gated onmoved_old(nowfalse) and is skipped — leaving the target deleted with no replacement. A failed update bricks the install.The fix
Extract the swap into
swap_in_new_bundle()with a strict invariant: on any failure path,targetis left pointing at a working bundle (the original — rolled back or untouched) and is never deleted with no replacement. Also clean up the staged.hermes-update-newcopy on the failure paths instead of orphaning it.Tests
Adds three
#[tokio::test]cases inupdate.rs:swap_installs_new_bundle_and_cleans_up— happy pathswap_rolls_back_when_install_step_fails— move-aside ok, install fails ⇒ original restoredswap_failure_never_leaves_target_missing— both moves fail ⇒ original survivesThe catastrophic-path test was verified to FAIL against the pre-fix code (
original app must NOT be deleted on failure) and pass against the fix, so it's a real regression guard.Scope:
apps/bootstrap-installer/src-tauri/src/update.rsonly. macOS-gated path; no behavior change on the success path.