From 77f5b2ad9d21dc61027ee30044cd581fa8218ca7 Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Wed, 27 May 2026 18:13:25 -0700 Subject: [PATCH] Preserve Electron framework symlinks (#2958) Preserve Electron framework symlinks --- .../install-electron-package-binary.mjs | 21 +++++++++++++++++-- .../install-electron-package-binary.test.mjs | 13 +++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/config/scripts/install-electron-package-binary.mjs b/config/scripts/install-electron-package-binary.mjs index cec2714cc28..25662d10755 100644 --- a/config/scripts/install-electron-package-binary.mjs +++ b/config/scripts/install-electron-package-binary.mjs @@ -127,8 +127,7 @@ async function installElectronPackageBinary() { process.exit(1) } - rmSync(electronDistDir, { recursive: true, force: true }) - cpSync(extractDir, electronDistDir, { recursive: true }) + moveExtractedElectronDist(extractDir, electronDistDir) const srcTypeDefPath = resolve(electronDistDir, 'electron.d.ts') if (existsSync(srcTypeDefPath)) { @@ -157,6 +156,24 @@ function extractElectronArchive(zipPath, extractDir) { } } +function moveExtractedElectronDist(extractDir, electronDistDir) { + rmSync(electronDistDir, { recursive: true, force: true }) + try { + // Why: macOS Electron archives rely on framework symlinks. Moving the + // verified tree preserves them exactly; copying has broken them in CI. + renameSync(extractDir, electronDistDir) + } catch (/** @type {any} */ err) { + if (err?.code !== 'EXDEV') { + throw err + } + cpSync(extractDir, electronDistDir, { + recursive: true, + dereference: false, + verbatimSymlinks: true + }) + } +} + function getExtractorCommand(zipPath, extractDir) { if (process.env.ORCA_ELECTRON_PACKAGE_EXTRACTOR) { return { diff --git a/config/scripts/install-electron-package-binary.test.mjs b/config/scripts/install-electron-package-binary.test.mjs index 54fa21a4c13..95c1057eb91 100644 --- a/config/scripts/install-electron-package-binary.test.mjs +++ b/config/scripts/install-electron-package-binary.test.mjs @@ -1,6 +1,7 @@ import { copyFileSync, existsSync, + lstatSync, mkdirSync, mkdtempSync, readFileSync, @@ -35,6 +36,13 @@ describe('install-electron-package-binary', () => { expect(readFileSync(join(projectDir, 'node_modules', 'electron', 'path.txt'), 'utf8')).toBe( 'electron' ) + if (process.platform !== 'win32') { + expect( + lstatSync( + join(projectDir, 'node_modules', 'electron', 'dist', 'version-link') + ).isSymbolicLink() + ).toBe(true) + } expect(result.stdout).toContain('Repaired Electron path.txt -> electron') } finally { rmSync(projectDir, { recursive: true, force: true }) @@ -153,13 +161,16 @@ function writeFakeExtractor(projectDir, { createExecutable }) { writeFileSync( join(projectDir, 'fake-extractor.cjs'), ` -const { mkdirSync, writeFileSync } = require('node:fs') +const { mkdirSync, symlinkSync, writeFileSync } = require('node:fs') const { join } = require('node:path') const extractDir = process.argv[3] mkdirSync(join(extractDir, 'locales'), { recursive: true }) if (${JSON.stringify(createExecutable)}) { writeFileSync(join(extractDir, 'electron'), '') writeFileSync(join(extractDir, 'version'), 'v41.5.0') + if (process.platform !== 'win32') { + symlinkSync('version', join(extractDir, 'version-link')) + } } ` )