fix(desktop): recover from corrupt Electron cache in bootstrap install (Windows)
Windows counterpart of #39127: scripts/install.ps1 `Install-Desktop` runs `npm run pack` once and throws on the opaque ENOENT a corrupt cached Electron download produces, with no recovery. Add `Clear-ElectronBuildCache` plus a purge-and-retry-once on pack failure, mirroring the install.sh fix: remove the cached electron-*.zip (%LOCALAPPDATA%\electron\Cache + ELECTRON_CACHE / electron_config_cache overrides) and stale *-unpacked output, then retry so @electron/get re-downloads with its own SHASUM verification. Refs #37544. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -1934,6 +1934,55 @@ function Install-NodeDeps {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Clear the cached Electron download + any half-written unpacked output so the
|
||||||
|
# next `npm run pack` re-downloads and re-stages from scratch. A corrupt zip in
|
||||||
|
# the per-user Electron download cache - most often a partial download resumed
|
||||||
|
# into the same file, leaving concatenated junk - makes electron-builder's
|
||||||
|
# `app-builder unpack-electron` extract a tree MISSING the electron binary, so
|
||||||
|
# the final `electron` -> `Hermes` rename dies with ENOENT and every re-run
|
||||||
|
# repeats the broken extraction forever.
|
||||||
|
#
|
||||||
|
# We deliberately do not validate the zip ourselves: the common
|
||||||
|
# prepended/concatenated-junk corruption slips past naive checks, so a
|
||||||
|
# self-rolled gate would skip the real-world case. We unconditionally drop the
|
||||||
|
# cached electron-*.zip (loose copy and any @electron/get hash-subdir copy) plus
|
||||||
|
# the stale unpacked dir, then let the caller retry once - @electron/get
|
||||||
|
# re-downloads with its own SHASUM verification, the real source of truth.
|
||||||
|
#
|
||||||
|
# Returns the removed paths. Best-effort: never throws.
|
||||||
|
function Clear-ElectronBuildCache {
|
||||||
|
param([string]$DesktopDir)
|
||||||
|
$removed = @()
|
||||||
|
|
||||||
|
# Per-user Electron download cache dirs, honoring the overrides @electron/get
|
||||||
|
# respects, then the Windows default (%LOCALAPPDATA%\electron\Cache).
|
||||||
|
$cacheDirs = @()
|
||||||
|
if ($env:electron_config_cache) { $cacheDirs += $env:electron_config_cache }
|
||||||
|
if ($env:ELECTRON_CACHE) { $cacheDirs += $env:ELECTRON_CACHE }
|
||||||
|
if ($env:LOCALAPPDATA) { $cacheDirs += (Join-Path $env:LOCALAPPDATA 'electron\Cache') }
|
||||||
|
$cacheDirs += (Join-Path $HOME 'AppData\Local\electron\Cache')
|
||||||
|
|
||||||
|
foreach ($dir in $cacheDirs) {
|
||||||
|
if (-not (Test-Path -LiteralPath $dir)) { continue }
|
||||||
|
# Recurse: the bad copy may be the top-level zip OR a copy inside an
|
||||||
|
# @electron/get hash subdir.
|
||||||
|
$removed += @(Get-ChildItem -LiteralPath $dir -Recurse -Filter 'electron-*.zip' -File -ErrorAction SilentlyContinue | ForEach-Object {
|
||||||
|
try { Remove-Item -LiteralPath $_.FullName -Force -ErrorAction Stop; $_.FullName } catch { }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
# A half-written unpacked dir from an interrupted prior pack poisons the
|
||||||
|
# rename even after the zip is fixed (win-unpacked / win-arm64-unpacked).
|
||||||
|
$releaseDir = Join-Path $DesktopDir 'release'
|
||||||
|
if (Test-Path -LiteralPath $releaseDir) {
|
||||||
|
$removed += @(Get-ChildItem -LiteralPath $releaseDir -Directory -Filter '*-unpacked' -ErrorAction SilentlyContinue | ForEach-Object {
|
||||||
|
try { Remove-Item -LiteralPath $_.FullName -Recurse -Force -ErrorAction Stop; $_.FullName } catch { }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return $removed
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
@ -2067,6 +2116,22 @@ function Install-Desktop {
|
|||||||
$env:WIN_CSC_KEY_PASSWORD = ""
|
$env:WIN_CSC_KEY_PASSWORD = ""
|
||||||
& $npmExe run pack 2>&1 | ForEach-Object { "$_" } | Tee-Object -FilePath $buildLog
|
& $npmExe run pack 2>&1 | ForEach-Object { "$_" } | Tee-Object -FilePath $buildLog
|
||||||
$code = $LASTEXITCODE
|
$code = $LASTEXITCODE
|
||||||
|
if ($code -ne 0) {
|
||||||
|
# A corrupt cached Electron zip makes `pack` fail with an opaque
|
||||||
|
# ENOENT on the final `electron` -> `Hermes` rename: app-builder's
|
||||||
|
# unpack-electron extracted a partial tree (missing the binary) from
|
||||||
|
# the bad zip, and re-running reuses the poisoned cache forever.
|
||||||
|
# Purge the cached download + any stale unpacked output and retry
|
||||||
|
# once; @electron/get re-downloads with its own SHASUM check. Without
|
||||||
|
# this a corrupt download hard-fails the whole installer.
|
||||||
|
$purged = @(Clear-ElectronBuildCache -DesktopDir $desktopDir)
|
||||||
|
if ($purged.Count -gt 0) {
|
||||||
|
Write-Warn "Desktop build failed - cleared cached Electron download, retrying once:"
|
||||||
|
foreach ($p in $purged) { Write-Info " - $p" }
|
||||||
|
& $npmExe run pack 2>&1 | ForEach-Object { "$_" } | Tee-Object -FilePath $buildLog
|
||||||
|
$code = $LASTEXITCODE
|
||||||
|
}
|
||||||
|
}
|
||||||
$ErrorActionPreference = $prevEAP
|
$ErrorActionPreference = $prevEAP
|
||||||
if ($code -ne 0) {
|
if ($code -ne 0) {
|
||||||
$errText = Get-Content $buildLog -Raw -ErrorAction SilentlyContinue
|
$errText = Get-Content $buildLog -Raw -ErrorAction SilentlyContinue
|
||||||
|
|||||||
Reference in New Issue
Block a user