mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-09 08:21:50 +00:00
fix(install.ps1): pre-warm electron-builder winCodeSign cache + fix Stage-Desktop $HasNode false-skip
Two bugs caught in the second VM end-to-end run: 1. electron-builder's winCodeSign extraction fails on grandma-class Windows boxes because the .7z archive contains macOS symlinks (darwin/10.12/lib/libcrypto.dylib and libssl.dylib pointing at versioned siblings). Creating symlinks on Windows requires SeCreateSymbolicLinkPrivilege, a per-user right that non-admin accounts don't have on stock Windows. Result: every fresh install on a non-admin user fails Stage-Desktop with a 7-Zip 'cannot create symbolic link' error, retried four times, then bails. Fix: Initialize-ElectronBuilderCache pre-extracts winCodeSign-2.6.0.7z ourselves with -snl (don't preserve symlinks, store as resolved file content) AND -x!darwin (skip the entire macOS subtree — irrelevant on Windows). Writes to electron-builder's expected cache dir before electron-builder gets a chance to try its own broken extraction. Idempotent — fast-paths via signtool.exe sentinel check. 2. Install-Desktop's first guard was 'if (-not $HasNode) skip'. $HasNode is set by Stage-Node into $script:HasNode, but in cross-process driver mode (each -Stage NAME is a fresh powershell.exe spawned by Hermes-Setup.exe), that script-scope variable from the PREVIOUS process is invisible — so the guard always fired and Install-Desktop returned in 900ms with a misleading 'Node.js not available' reason. The real npm probe below it never got to run. Fix: re-probe npm directly via Get-Command when $HasNode is empty/false, since by that point Stage-Node has already verified Node is installed and the only question is whether *this* process can see it on PATH (it can — installer-wide PATH update from Stage-Node).
This commit is contained in:
parent
0a079f7321
commit
c7e46f9f3d
1 changed files with 116 additions and 3 deletions
|
|
@ -1837,6 +1837,106 @@ function Install-NodeDeps {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Initialize-ElectronBuilderCache {
|
||||||
|
# Pre-warm electron-builder's winCodeSign cache so it never tries to
|
||||||
|
# extract the .7z archive itself.
|
||||||
|
#
|
||||||
|
# The bug we're working around: winCodeSign-2.6.0.7z contains macOS
|
||||||
|
# symbolic links under darwin/10.12/lib/ (libcrypto.dylib, libssl.dylib
|
||||||
|
# pointing at versioned siblings). On Windows, 7-Zip's extraction of
|
||||||
|
# those symlinks requires SeCreateSymbolicLinkPrivilege — a per-user
|
||||||
|
# right that non-admin accounts on stock Windows don't have. So
|
||||||
|
# electron-builder fails the extraction every time it pulls a fresh
|
||||||
|
# cache, on every grandma-class box.
|
||||||
|
#
|
||||||
|
# The fix: do the extraction ourselves with `-x!darwin` to skip the
|
||||||
|
# entire macOS subtree. electron-builder is doing a WINDOWS build —
|
||||||
|
# it never reads anything under darwin/ on this code path. As long
|
||||||
|
# as the cache directory exists with the Windows-relevant files,
|
||||||
|
# electron-builder's "is the cache present?" check passes and it
|
||||||
|
# skips its own extraction entirely.
|
||||||
|
#
|
||||||
|
# Tooling: we use 7za.exe from the 7zip-bin npm package that
|
||||||
|
# electron-builder itself depends on (so we know it's present after
|
||||||
|
# the workspace `npm install` finishes). Falls back to no-op if
|
||||||
|
# neither is found — electron-builder will then attempt its own
|
||||||
|
# broken extraction and fail with a recognizable error.
|
||||||
|
|
||||||
|
$cacheRoot = "$env:LOCALAPPDATA\electron-builder\Cache\winCodeSign"
|
||||||
|
$extractedDir = "$cacheRoot\winCodeSign-2.6.0"
|
||||||
|
$sentinel = "$extractedDir\windows-10\x64\signtool.exe"
|
||||||
|
|
||||||
|
# Fast-path: already populated from a prior run.
|
||||||
|
if (Test-Path $sentinel) {
|
||||||
|
Write-Info "electron-builder winCodeSign cache already populated"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
# Locate 7za.exe. electron-builder hoists 7zip-bin to the workspace
|
||||||
|
# root node_modules so apps/desktop's pack step can find it.
|
||||||
|
$sevenZip = "$InstallDir\node_modules\7zip-bin\win\x64\7za.exe"
|
||||||
|
if (-not (Test-Path $sevenZip)) {
|
||||||
|
# Some npm versions don't hoist; check apps/desktop's local copy.
|
||||||
|
$sevenZip = "$InstallDir\apps\desktop\node_modules\7zip-bin\win\x64\7za.exe"
|
||||||
|
}
|
||||||
|
if (-not (Test-Path $sevenZip)) {
|
||||||
|
Write-Warn "7za.exe not found in node_modules; electron-builder may fail to extract winCodeSign"
|
||||||
|
Write-Warn " Looked at: $InstallDir\node_modules\7zip-bin\win\x64\7za.exe"
|
||||||
|
Write-Warn " and: $InstallDir\apps\desktop\node_modules\7zip-bin\win\x64\7za.exe"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
New-Item -ItemType Directory -Force -Path $cacheRoot | Out-Null
|
||||||
|
|
||||||
|
# Download to a TEMP path; electron-builder doesn't care about the
|
||||||
|
# archive itself once the extracted dir exists.
|
||||||
|
$tmpArchive = "$env:TEMP\hermes-wincodesign-$(Get-Random).7z"
|
||||||
|
$url = "https://github.com/electron-userland/electron-builder-binaries/releases/download/winCodeSign-2.6.0/winCodeSign-2.6.0.7z"
|
||||||
|
|
||||||
|
Write-Info "Pre-extracting winCodeSign to skip electron-builder's broken extraction..."
|
||||||
|
try {
|
||||||
|
Invoke-WebRequest -Uri $url -OutFile $tmpArchive -UseBasicParsing -ErrorAction Stop
|
||||||
|
} catch {
|
||||||
|
Write-Warn "Failed to download winCodeSign: $_"
|
||||||
|
Write-Warn " electron-builder will fall back to its own extraction (which fails on non-admin Windows)"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
# 7-Zip flags:
|
||||||
|
# x extract with full paths
|
||||||
|
# -y assume yes on all prompts
|
||||||
|
# -bd no progress bar (silent)
|
||||||
|
# -snl do NOT extract symbolic links as links — store as the
|
||||||
|
# resolved file content instead. This is what stops the
|
||||||
|
# privilege-not-held crash on the darwin/*.dylib symlinks.
|
||||||
|
# -x!darwin exclude the entire darwin/ subtree (macOS-specific
|
||||||
|
# code-signing tools that a Windows build doesn't need)
|
||||||
|
# -o<dir> output directory
|
||||||
|
#
|
||||||
|
# Belt-and-suspenders: we BOTH skip the darwin subtree AND tell 7-Zip
|
||||||
|
# to dereference any remaining symlinks. Either alone would fix it;
|
||||||
|
# together they're defensive against winCodeSign adding more symlinks
|
||||||
|
# under linux/ or appxAssets/ in some future release.
|
||||||
|
$prevEAP = $ErrorActionPreference
|
||||||
|
$ErrorActionPreference = "Continue"
|
||||||
|
& $sevenZip x -y -bd -snl "-x!darwin" "-o$cacheRoot" $tmpArchive 2>&1 | Out-Null
|
||||||
|
$code = $LASTEXITCODE
|
||||||
|
$ErrorActionPreference = $prevEAP
|
||||||
|
|
||||||
|
Remove-Item -Force $tmpArchive -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
if ($code -ne 0) {
|
||||||
|
Write-Warn "Pre-extraction of winCodeSign failed (7-Zip exit $code)"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path $sentinel) {
|
||||||
|
Write-Success "winCodeSign cache pre-populated at $extractedDir"
|
||||||
|
} else {
|
||||||
|
Write-Warn "winCodeSign extraction completed but expected file is missing: $sentinel"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function Install-Desktop {
|
function Install-Desktop {
|
||||||
# Build apps/desktop into a launchable Hermes.exe. Only called from
|
# Build apps/desktop into a launchable Hermes.exe. Only called from
|
||||||
# Stage-Desktop, which is itself only included in the manifest when
|
# Stage-Desktop, which is itself only included in the manifest when
|
||||||
|
|
@ -1856,9 +1956,15 @@ function Install-Desktop {
|
||||||
# don't need to produce an NSIS/MSI artifact here.
|
# don't need to produce an NSIS/MSI artifact here.
|
||||||
|
|
||||||
if (-not $HasNode) {
|
if (-not $HasNode) {
|
||||||
Write-Warn "Skipping desktop build (Node.js not installed)"
|
# Cross-process driver mode: each `-Stage NAME` invocation runs in a
|
||||||
$script:_StageSkippedReason = "Node.js not available"
|
# fresh PowerShell process, so $script:HasNode set by Stage-Node
|
||||||
return
|
# in the previous process isn't visible. Re-detect rather than
|
||||||
|
# trusting the global.
|
||||||
|
if (-not (Get-Command npm -ErrorAction SilentlyContinue)) {
|
||||||
|
Write-Warn "Skipping desktop build (Node.js / npm not on PATH)"
|
||||||
|
$script:_StageSkippedReason = "Node.js not available"
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$desktopDir = "$InstallDir\apps\desktop"
|
$desktopDir = "$InstallDir\apps\desktop"
|
||||||
|
|
@ -1913,6 +2019,13 @@ function Install-Desktop {
|
||||||
}
|
}
|
||||||
Pop-Location
|
Pop-Location
|
||||||
|
|
||||||
|
# Pre-warm electron-builder's winCodeSign cache so its own broken
|
||||||
|
# 7-Zip extraction doesn't fire later. Has to happen AFTER the
|
||||||
|
# workspace npm install (we need 7za.exe from 7zip-bin) but BEFORE
|
||||||
|
# `npm run pack` (which triggers electron-builder's first cache miss).
|
||||||
|
# See Initialize-ElectronBuilderCache for the full rationale.
|
||||||
|
Initialize-ElectronBuilderCache
|
||||||
|
|
||||||
# 2. Build apps/desktop. `npm run pack` runs:
|
# 2. Build apps/desktop. `npm run pack` runs:
|
||||||
# assert-root-install + write-build-stamp + stage-native-deps +
|
# assert-root-install + write-build-stamp + stage-native-deps +
|
||||||
# tsc -b + vite build + electron-builder --dir
|
# tsc -b + vite build + electron-builder --dir
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue