fix(desktop): resolve electronDist to the actual electron install location (#48081)

After the June lockfile regeneration (#46652) floated electron and reshuffled
npm workspace hoisting, the desktop pack fails with "The specified electronDist
does not exist". apps/desktop/package.json pointed electronDist at the repo
root (../../node_modules/electron/dist) while npm now installs electron nested
under apps/desktop/node_modules/electron. The two contradict, so a clean
install can never package the app (Windows + macOS).

- electronDist -> node_modules/electron/dist (resolved relative to apps/desktop,
  i.e. the workspace-local install npm actually produces).
- hermes_cli/main.py, scripts/install.sh, scripts/install.ps1: add a runtime
  electron-dir resolver that prefers apps/desktop/node_modules/electron and
  falls back to the root hoist, so dist checks + the mirror re-download work
  under either npm layout.
- patch-electron-builder-mac-binary.cjs: try the workspace-local Electron.app
  before the root hoist in the macOS binary-restore fallback (sibling site no
  PR touched).
- test: assert build.electronDist resolves to where the lockfile installs
  electron, so a future hoist change (root <-> nested) can't silently break it.

Salvages the overlapping work in #48003 (sitkarev), #48012 (omegazheng), and
#48033 (james47kjv).

Co-authored-by: sitkarev <59806492+sitkarev@users.noreply.github.com>
Co-authored-by: omegazheng <zheng@omegasys.eu>
Co-authored-by: james47kjv <220877172+james47kjv@users.noreply.github.com>
This commit is contained in:
Teknium 2026-06-17 16:08:01 -07:00 committed by GitHub
parent 016bce1a09
commit f8098c6b6f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 167 additions and 46 deletions

View file

@ -2161,28 +2161,41 @@ function Clear-ElectronBuildCache {
return $removed
}
# True when node_modules\electron\dist holds a usable Electron binary.
# electron-builder reads the binary from build.electronDist
# (node_modules\electron\dist) since #38673, so this is the exact file whose
# absence makes a pack fail with "The specified electronDist does not exist". A
# dist dir that exists but is missing electron.exe (partial extraction / aborted
# postinstall) is NOT ok.
# Return the Electron package directory the desktop workspace installs. npm may
# nest workspace-only dev dependencies under apps\desktop\node_modules instead
# of hoisting them to the repo root; which layout you get depends on the npm
# version and what else is installed. apps\desktop\package.json points
# electron-builder's electronDist there, so prefer the workspace-local package
# and fall back to the root hoist.
function Get-ElectronDir {
param([string]$InstallDir)
$desktopLocal = Join-Path $InstallDir 'apps\desktop\node_modules\electron'
if (Test-Path -LiteralPath $desktopLocal) { return $desktopLocal }
return (Join-Path $InstallDir 'node_modules\electron')
}
# True when the desktop workspace electronDist holds a usable Electron binary.
# electron-builder reads the binary from build.electronDist since #38673, so
# this is the exact file whose absence makes a pack fail with "The specified
# electronDist does not exist". A dist dir that exists but is missing
# electron.exe (partial extraction / aborted postinstall) is NOT ok.
function Test-ElectronDist {
param([string]$InstallDir)
$distExe = Join-Path $InstallDir 'node_modules\electron\dist\electron.exe'
$electronDir = Get-ElectronDir -InstallDir $InstallDir
$distExe = Join-Path $electronDir 'dist\electron.exe'
return (Test-Path -LiteralPath $distExe)
}
# (Re)populate node_modules\electron\dist via electron's own downloader.
# (Re)populate the desktop Electron dist via electron's own downloader.
#
# Since #38673 the desktop build pins build.electronDist to
# node_modules\electron\dist, so electron-builder reads the Electron binary
# straight from there and never downloads it during `npm run pack`. That dist
# tree is produced by the electron package's postinstall (install.js) during
# `npm ci`. When that download is blocked/throttled (GitHub's release host is
# unreachable in some regions - #47266), dist is missing and re-running pack only
# re-throws "The specified electronDist does not exist". The mirror fallback
# therefore has to drive THIS downloader, not another pack.
# Since #38673 the desktop build pins build.electronDist, so electron-builder
# reads the Electron binary straight from there and never downloads it during
# `npm run pack`. That dist tree is produced by the electron package's
# postinstall (install.js) during `npm ci`. When that download is
# blocked/throttled (GitHub's release host is unreachable in some regions -
# #47266), dist is missing and re-running pack only re-throws "The specified
# electronDist does not exist". The mirror fallback therefore has to drive THIS
# downloader, not another pack.
#
# No-op (returns $true) when the dist binary is already present. Otherwise drops a
# partial dist + version marker (electron's install.js short-circuits when
@ -2193,7 +2206,7 @@ function Restore-ElectronDist {
param([string]$InstallDir, [string]$Mirror)
if (Test-ElectronDist -InstallDir $InstallDir) { return $true }
$electronDir = Join-Path $InstallDir 'node_modules\electron'
$electronDir = Get-ElectronDir -InstallDir $InstallDir
$distExe = Join-Path $electronDir 'dist\electron.exe'
$installer = Join-Path $electronDir 'install.js'
if (-not (Test-Path -LiteralPath $installer)) { return $false }

View file

@ -2407,15 +2407,31 @@ _desktop_pack() {
# failed, and we never override a user-pinned ELECTRON_MIRROR.
DESKTOP_ELECTRON_FALLBACK_MIRROR="https://npmmirror.com/mirrors/electron/"
# True (returns 0) when node_modules/electron/dist holds a usable Electron
# binary. electron-builder reads the binary from build.electronDist
# (node_modules/electron/dist) since #38673, so this is the exact file whose
# absence makes a pack fail with "The specified electronDist does not exist". A
# dist dir that exists but is missing the binary (partial extraction / aborted
# postinstall) is NOT ok. $1 = the workspace root holding node_modules.
# Return the Electron package directory the desktop workspace installs. npm may
# nest workspace-only dev dependencies under apps/desktop/node_modules instead
# of hoisting them to the repo root; which layout you get depends on the npm
# version and what else is installed. apps/desktop/package.json points
# electron-builder's electronDist there, so prefer the workspace-local package
# and fall back to the root hoist. $1 = the workspace root holding node_modules.
_electron_dir() {
local install_dir="$1"
if [ -d "$install_dir/apps/desktop/node_modules/electron" ]; then
printf '%s\n' "$install_dir/apps/desktop/node_modules/electron"
else
printf '%s\n' "$install_dir/node_modules/electron"
fi
}
# True (returns 0) when the desktop workspace electronDist holds a usable
# Electron binary. electron-builder reads the binary from build.electronDist
# since #38673, so this is the exact file whose absence makes a pack fail with
# "The specified electronDist does not exist". A dist dir that exists but is
# missing the binary (partial extraction / aborted postinstall) is NOT ok.
# $1 = the workspace root holding node_modules.
_electron_dist_ok() {
local install_dir="$1"
local electron_dir="$install_dir/node_modules/electron"
local electron_dir
electron_dir="$(_electron_dir "$install_dir")"
if [ "$OS" = "macos" ]; then
[ -e "$electron_dir/dist/Electron.app/Contents/MacOS/Electron" ]
else
@ -2423,16 +2439,16 @@ _electron_dist_ok() {
fi
}
# (Re)populate node_modules/electron/dist via electron's own downloader.
# (Re)populate the desktop Electron dist via electron's own downloader.
#
# Since #38673 the desktop build pins build.electronDist to
# node_modules/electron/dist, so electron-builder reads the Electron binary
# straight from there and never downloads it during `npm run pack`. That dist
# tree is produced by the electron package's postinstall (install.js) during
# `npm ci`. When that download is blocked/throttled (GitHub's release host is
# unreachable in some regions - #47266), dist is missing and re-running pack only
# re-throws "The specified electronDist does not exist". The mirror fallback
# therefore has to drive THIS downloader, not another pack.
# Since #38673 the desktop build pins build.electronDist, so electron-builder
# reads the Electron binary straight from there and never downloads it during
# `npm run pack`. That dist tree is produced by the electron package's
# postinstall (install.js) during `npm ci`. When that download is
# blocked/throttled (GitHub's release host is unreachable in some regions -
# #47266), dist is missing and re-running pack only re-throws "The specified
# electronDist does not exist". The mirror fallback therefore has to drive THIS
# downloader, not another pack.
#
# No-op (returns 0) when the dist binary is already present. Otherwise drops a
# partial dist + version marker (electron's install.js short-circuits when
@ -2442,7 +2458,8 @@ _electron_dist_ok() {
_restore_electron_dist() {
local install_dir="$1"
local mirror="${2:-}"
local electron_dir="$install_dir/node_modules/electron"
local electron_dir
electron_dir="$(_electron_dir "$install_dir")"
_electron_dist_ok "$install_dir" && return 0
[ -f "$electron_dir/install.js" ] || return 1

View file

@ -45,6 +45,9 @@ ACP_REGISTRY_MANIFEST = REPO_ROOT / "acp_registry" / "agent.json"
# Auto-extracted from noreply emails + manual overrides
AUTHOR_MAP = {
"59806492+sitkarev@users.noreply.github.com": "sitkarev",
"zheng@omegasys.eu": "omegazheng",
"220877172+james47kjv@users.noreply.github.com": "james47kjv",
"yuhanglin@YuhangdeMac-mini.local": "1960697431",
"despitemeguru@gmail.com": "definitelynotguru",
"chaslui@outlook.com": "ChasLui",