Repair Electron startup and install CI deps
Template tests / tests (push) Failing after 15s

This commit is contained in:
Iisyourdad
2026-06-10 19:01:58 -05:00
parent 814a593887
commit 3bcac9f673
4 changed files with 91 additions and 1 deletions
+3
View File
@@ -16,5 +16,8 @@ jobs:
- name: Checkout repository - name: Checkout repository
uses: https://gitea.com/actions/checkout@v4 uses: https://gitea.com/actions/checkout@v4
- name: Install dependencies
run: npm ci
- name: Run template tests - name: Run template tests
run: bash tests/run_test.sh run: bash tests/run_test.sh
+54
View File
@@ -1,5 +1,6 @@
'use strict'; 'use strict';
const { spawnSync } = require('node:child_process');
const fs = require('node:fs'); const fs = require('node:fs');
const path = require('node:path'); const path = require('node:path');
@@ -34,6 +35,41 @@ function platformBinaryCandidates(platform) {
} }
} }
function repairElectronInstall({
packageRoot,
platform = process.platform,
arch = process.arch,
}) {
const installScript = path.join(packageRoot, 'install.js');
if (!fs.existsSync(installScript)) {
return false;
}
const result = spawnSync(process.execPath, [installScript], {
cwd: packageRoot,
env: {
...process.env,
npm_config_platform: platform,
npm_config_arch: arch,
},
stdio: 'inherit',
});
if (result.error) {
throw result.error;
}
if (result.signal) {
throw new Error(`Electron repair was interrupted by ${result.signal}`);
}
if (result.status !== 0) {
throw new Error(`Electron repair failed with exit code ${result.status ?? 1}`);
}
return true;
}
function buildMissingElectronError({ packageRoot, distDir, candidatePaths }) { function buildMissingElectronError({ packageRoot, distDir, candidatePaths }) {
const tried = candidatePaths.map((candidate) => ` - ${candidate}`).join('\n'); const tried = candidatePaths.map((candidate) => ` - ${candidate}`).join('\n');
return [ return [
@@ -57,6 +93,7 @@ function resolveElectronBinary({
packageRoot = resolveElectronPackageRoot(), packageRoot = resolveElectronPackageRoot(),
platform = process.platform, platform = process.platform,
overrideDistPath = process.env.ELECTRON_OVERRIDE_DIST_PATH || null, overrideDistPath = process.env.ELECTRON_OVERRIDE_DIST_PATH || null,
arch = process.arch,
} = {}) { } = {}) {
if (!packageRoot && !overrideDistPath) { if (!packageRoot && !overrideDistPath) {
throw new Error( throw new Error(
@@ -79,6 +116,22 @@ function resolveElectronBinary({
const resolved = candidatePaths.find((candidate) => fs.existsSync(candidate)); const resolved = candidatePaths.find((candidate) => fs.existsSync(candidate));
if (!resolved) { if (!resolved) {
if (packageRoot && repairElectronInstall({ packageRoot, platform, arch })) {
const repairedHint = readElectronPathHint(packageRoot);
const repairedCandidates = [];
if (repairedHint) {
repairedCandidates.push(path.join(distDir, repairedHint));
}
for (const relativePath of platformBinaryCandidates(platform)) {
repairedCandidates.push(path.join(distDir, relativePath));
}
const repaired = repairedCandidates.find((candidate) => fs.existsSync(candidate));
if (repaired) {
return repaired;
}
}
throw new Error(buildMissingElectronError({ packageRoot, distDir, candidatePaths })); throw new Error(buildMissingElectronError({ packageRoot, distDir, candidatePaths }));
} }
@@ -88,6 +141,7 @@ function resolveElectronBinary({
module.exports = { module.exports = {
buildMissingElectronError, buildMissingElectronError,
readElectronPathHint, readElectronPathHint,
repairElectronInstall,
resolveElectronBinary, resolveElectronBinary,
resolveElectronPackageRoot, resolveElectronPackageRoot,
platformBinaryCandidates, platformBinaryCandidates,
+7 -1
View File
@@ -5,7 +5,13 @@ const { spawn } = require('node:child_process');
const { resolveElectronBinary } = require('./electron-launcher'); const { resolveElectronBinary } = require('./electron-launcher');
const electronPath = resolveElectronBinary(); let electronPath;
try {
electronPath = resolveElectronBinary();
} catch (error) {
console.error(error && error.message ? error.message : error);
process.exit(1);
}
const env = { ...process.env }; const env = { ...process.env };
delete env.ELECTRON_RUN_AS_NODE; delete env.ELECTRON_RUN_AS_NODE;
+27
View File
@@ -7,6 +7,7 @@ const path = require('node:path');
const { const {
buildMissingElectronError, buildMissingElectronError,
repairElectronInstall,
resolveElectronBinary, resolveElectronBinary,
} = require('../../scripts/electron-launcher'); } = require('../../scripts/electron-launcher');
const { makeTmpDir, rmrf } = require('./helpers'); const { makeTmpDir, rmrf } = require('./helpers');
@@ -38,6 +39,32 @@ test('falls back to the platform binary when path.txt is absent', (t) => {
); );
}); });
test('repairs a broken Electron install before resolving the binary', (t) => {
const root = makeTmpDir('electron-repair');
t.after(() => rmrf(root));
fs.mkdirSync(path.join(root, 'dist'), { recursive: true });
fs.writeFileSync(
path.join(root, 'install.js'),
[
"const fs = require('node:fs');",
"const path = require('node:path');",
"fs.mkdirSync(path.join(__dirname, 'dist'), { recursive: true });",
"fs.writeFileSync(path.join(__dirname, 'dist', 'electron.exe'), 'binary');",
"fs.writeFileSync(path.join(__dirname, 'path.txt'), 'electron.exe');",
].join('\n')
);
assert.equal(
repairElectronInstall({ packageRoot: root, platform: 'win32' }),
true
);
assert.equal(
resolveElectronBinary({ packageRoot: root, platform: 'win32' }),
path.join(root, 'dist', 'electron.exe')
);
});
test('reports a helpful error when the runtime is missing', (t) => { test('reports a helpful error when the runtime is missing', (t) => {
const root = makeTmpDir('electron-missing'); const root = makeTmpDir('electron-missing');
t.after(() => rmrf(root)); t.after(() => rmrf(root));