fix(desktop): stop hermes desktop from clobbering tracked main.cjs (#52735)

`npm run build` ended with `bundle-electron-main.mjs`, which esbuild-bundled
electron/main.cjs and renamed the bundle on top of the tracked source file.
Because every `hermes desktop` runs `npm run build`, each launch rewrote a
checked-in source file (~7.5k-line source -> ~14.8k-line bundle), dirtying the
working tree with a build artifact that `git restore` couldn't keep (the next
launch re-clobbered it) and forcing autostash/restore conflicts on update.

The bundle only existed to inline `simple-git` so the packaged app.asar (which
ships no node_modules) wouldn't crash at launch with "Cannot find module
'simple-git'". Replace it with the mechanism the repo already uses for the
other hoisted runtime dep (node-pty): stage the dependency closure and resolve
it from process.resourcesPath at runtime.

- stage-native-deps.cjs: resolve simple-git's runtime closure (walking
  dependencies + optionalDependencies, so a version bump that adds a transitive
  dep can't silently reintroduce the crash) and stage it under
  build/native-deps/vendor/node_modules/. The `vendor/` nesting is load-bearing:
  electron-builder drops a node_modules dir at the ROOT of an extraResources
  copy but keeps a nested one.
- git-review-ops.cjs: fall back to the staged
  native-deps/vendor/node_modules/simple-git when the hoisted require() fails;
  dev runs resolve the hoisted copy and never hit the fallback.
- package.json: drop the bundler from the `build` script so main.cjs is never a
  build target again.
- nix/desktop.nix: drop the direct bundler call (the closure rides the existing
  `cp -rn native-deps` into $out) and patch process.resourcesPath in
  git-review-ops.cjs alongside main.cjs.
- delete scripts/bundle-electron-main.mjs.

Verified: electron-builder's own file filter keeps the full staged closure
(0 dropped), and a packaged win-unpacked build launches with the git-review
pane resolving simple-git from the staged vendor path.
This commit is contained in:
emozilla
2026-06-28 01:07:54 -04:00
parent 6514be5a28
commit 2d206a3a42
5 changed files with 161 additions and 42 deletions

View File

@@ -55,13 +55,15 @@ let
npm exec tsc -b
npm exec vite build
# Bundle the electron main into a single self-contained file so
# the nix output doesn't need node_modules/. simple-git (the only
# external runtime dep of the electron main) gets inlined; electron
# and node-pty are external (provided by the runtime / native-deps).
# preload.cjs stays separate — Electron loads it via __dirname, not
# require(), so it must remain a standalone file.
node scripts/bundle-electron-main.mjs
# simple-git is the electron main's external runtime dep. It is not
# bundled into main.cjs; instead the stage-native-deps.cjs call above
# copies its closure to apps/desktop/build/native-deps/vendor/node_modules/,
# which installPhase ships into $out/native-deps/ — the same path the
# packaged app uses. electron/git-review-ops.cjs resolves it from
# process.resourcesPath when the hoisted require() isn't reachable
# (see issue #52735). node-pty's prebuilt is staged the same way;
# electron is provided by the runtime. preload.cjs stays separate —
# Electron loads it via __dirname, not require().
popd
runHook postBuild
@@ -131,6 +133,13 @@ stdenv.mkDerivation {
substituteInPlace $out/share/hermes-desktop/electron/main.cjs \
--replace-fail "process.resourcesPath" "'$out/share/hermes-desktop'"
# git-review-ops.cjs has the same process.resourcesPath fallback for its
# staged simple-git dep (native-deps/vendor/node_modules/), so it needs the same
# rewrite — otherwise the require() fallback resolves against the electron
# dist's resources path and fails to load simple-git (issue #52735).
substituteInPlace $out/share/hermes-desktop/electron/git-review-ops.cjs \
--replace-fail "process.resourcesPath" "'$out/share/hermes-desktop'"
# Wrap the nixpkgs electron binary to launch our app. Set
# HERMES_DESKTOP_HERMES to the absolute path of the nix-built `hermes`
# binary so the desktop's resolver step 4 ("existing Hermes CLI on