fix(desktop): preserve the packaged app when an Electron rebuild fails#44234
fix(desktop): preserve the packaged app when an Electron rebuild fails#44234AIalliAI wants to merge 1 commit into
Conversation
before-pack.cjs deliberately wipes appOutDir (release/win-unpacked with the live Hermes.exe) so packs always stage into a clean tree, but the Electron download/extract runs after that wipe — so a pack that fails (corrupt cached zip, blocked download, proxy timeout) destroyed the only executable the user had, and the desktop shortcut became a dead link. hermes update triggers exactly this rebuild after git pull, including from the GUI's Update Now button. Park the current unpacked app under release/.rebuild-backup/ (cheap same-volume rename) before invoking the pack, restore it if every retry fails (or if a zero-exit pack produces no launchable app), and discard it once a fresh build exists. The holder directory sits outside both the release/*-unpacked glob that _purge_electron_build_cache clears between retries and the mac* glob _desktop_packaged_executable uses for detection, so the parked copy can't be purged mid-retry or mistaken for a fresh build. Best-effort: if the rename fails, behavior is exactly as before. Fixes NousResearch#44225 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Code Review — looks solid The backup-before-pack approach is well-designed. A few things verified:
One minor note: |
|
Related: competing fix for #44225 alongside #44238. This PR parks the unpacked app in a |
|
Requesting maintainer review — this is ready to land from my side. Standalone fork CI is pending first-run approval here; the rollup branch in #44061 carrying this session's batch is fully green on upstream CI (all test shards, typecheck, e2e). |
Fixes #44225
Problem
hermes update(including the desktop GUI's Update Now) rebuilds the desktop app viahermes desktop --build-onlyaftergit pull. electron-builder'sbeforePackhook (apps/desktop/scripts/before-pack.cjs) wipesappOutDir— e.g.release/win-unpacked/containing the liveHermes.exe— before staging, and the Electron download/extract runs after that wipe. So any pack failure (corrupt cached Electron zip, blocked/timed-out download) destroys the only executable the user has: the desktop shortcut becomes a dead link and the app is gone until a manual rebuild succeeds.The CLI's existing retry ladder (cache purge → retry → mirror fallback) reduces how often the pack fails, but restores nothing when all retries fail.
Fix
In the packaged-build path of
_cmd_desktop(so it covershermes update, GUI-triggered updates, the installer's headless--updaterebuild, and manualhermes desktop --force-buildalike):release/.rebuild-backup/<name>(_backup_desktop_unpacked_app). ThebeforePackhook's stale-dir cleanup semantics are preserved — it simply finds a clean tree._restore_desktop_unpacked_app), then fail with the same exit code as before.The holder directory is deliberately not a sibling rename:
_purge_electron_build_cachermtree'srelease/*-unpackedbetween retries and_desktop_packaged_executableglobsmac*, so a sibling name would either get purged mid-retry or be mistaken for the freshly-built app. There's a regression test pinning each of those interactions.All helpers are best-effort and never raise; if the backup rename fails, behavior is exactly what it was before this change.
This is the issue's proposed option A/B, but placed in the CLI pack path rather than
_cmd_update_impl(option A would miss manual rebuilds) orbefore-pack.cjs(electron-builder has no on-failure hook to drive a restore from).Tests
8 new tests in
tests/hermes_cli/test_gui_command.py: backup/restore unit coverage (including the macOSHermes.app→appOutDirresolution), the purge-glob and detection-glob non-interference pins, and end-to-endcmd_guiruns for fail-restores / success-discards / zero-exit-without-artifact-restores.tests/hermes_cli/test_gui_command.py(36) andtests/hermes_cli/test_cmd_update.py(29) all pass.🤖 Generated with Claude Code