Files
claude-desktop-debian/scripts/setup/fetch-electron-binary.js
aaddrick 3b86003a6b fix(deps): pin electron@41.5.0 to match upstream app.asar ABI
Re-add the exact Electron version pin that #586 had, hoisted to a
named local in scripts/setup/dependencies.sh so the next bump is
intentional. Upstream Claude Desktop's app.asar binds to a specific
V8/NAPI ABI, Chromium pairing, and node-pty native surface; running
a different Electron major against it is unsupported and was the
reproducibility hole left when this PR dropped the ^41 pin.

Also:
- Wrap node fetch-electron-binary.js in a 2-attempt retry so a
  transient 503 from electron's CDN doesn't red the whole build.
- Whitelist supported archs (x64, arm64, armv7l, ia32) with an
  actionable error in fetch-electron-binary.js, instead of 404'ing
  on electron's release server for exotic-arch hosts.
- Document ELECTRON_MIRROR / ELECTRON_CUSTOM_DIR in docs/BUILDING.md
  and clarify that ELECTRON_CACHE is NOT honored by @electron/get
  (the original PR body's claim was wrong).

Refs #584. Addresses self-review feedback on #587.

Co-Authored-By: Claude <claude@anthropic.com>
2026-05-14 06:04:42 -04:00

78 lines
2.4 KiB
JavaScript

#!/usr/bin/env node
// Fetches the Electron prebuilt binary into node_modules/electron/dist/.
//
// electron@42.0.0 (2026-05-06) removed the postinstall script that
// historically populated dist/ during `npm install`. This helper restores
// that behavior using @electron/get + extract-zip, so the rest of the
// build pipeline (which depends on the dist/ layout) keeps working.
//
// Run from the directory containing node_modules/electron. Reads the
// installed electron version from its package.json and downloads the
// matching binary for the host platform/arch.
//
// See: https://github.com/aaddrick/claude-desktop-debian/issues/584
'use strict';
const fs = require('node:fs');
const path = require('node:path');
async function main() {
const cwd = process.cwd();
const electronModuleDir = path.join(cwd, 'node_modules', 'electron');
const distDir = path.join(electronModuleDir, 'dist');
if (!fs.existsSync(electronModuleDir)) {
throw new Error(
`Electron module not found at ${electronModuleDir}; ` +
"run 'npm install electron' first.",
);
}
const pkgPath = path.join(electronModuleDir, 'package.json');
const { version } = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
if (!version) {
throw new Error(`Could not read version from ${pkgPath}`);
}
const platform = 'linux';
// node's process.arch values map cleanly to electron release archs,
// except 'arm' which electron publishes as 'armv7l'.
const arch = process.arch === 'arm' ? 'armv7l' : process.arch;
const supportedArchs = ['x64', 'arm64', 'armv7l', 'ia32'];
if (!supportedArchs.includes(arch)) {
throw new Error(
`Unsupported architecture: ${arch}. ` +
`Electron publishes Linux binaries for ${supportedArchs.join(', ')}.`,
);
}
const { downloadArtifact } = require('@electron/get');
const extractZip = require('extract-zip');
console.log(`Fetching electron@${version} for ${platform}-${arch}...`);
const zipPath = await downloadArtifact({
version,
platform,
arch,
artifactName: 'electron',
});
console.log(`Extracting ${zipPath} into ${distDir}`);
fs.mkdirSync(distDir, { recursive: true });
await extractZip(zipPath, { dir: distDir });
const electronBin = path.join(distDir, 'electron');
if (fs.existsSync(electronBin)) {
fs.chmodSync(electronBin, 0o755);
}
console.log('Electron binary fetched and extracted successfully.');
}
main().catch((err) => {
console.error(err && err.stack ? err.stack : err);
process.exit(1);
});