feat(ci): use patched Linux Electron from GitHub release
Build and Release / build-and-release (push) Failing after 3m51s

Rewrite download-electron.js to download both Windows (v42) and
Linux (v43) patched binaries from bigjakk/Electron-Websocket-Fix,
matching KPC's multi-platform approach. On CI, binaries go to
dist-win/ and dist-linux/; locally the current platform replaces
dist/. Both platforms now use the patched Electron.
This commit is contained in:
2026-04-03 18:05:16 -07:00
parent 11b585d409
commit 21e402b9d3
2 changed files with 195 additions and 191 deletions
+1 -13
View File
@@ -56,18 +56,6 @@ jobs:
if: steps.version-check.outputs.SKIP == 'false' if: steps.version-check.outputs.SKIP == 'false'
run: npm ci --legacy-peer-deps run: npm ci --legacy-peer-deps
- name: Ensure Electron Linux binary
if: steps.version-check.outputs.SKIP == 'false'
run: |
if [ ! -f node_modules/electron/dist/electron ]; then
echo "Electron Linux binary not found in dist/, triggering download..."
node node_modules/electron/install.js
fi
echo "=== Electron binaries ==="
echo "dist/electron: $(ls -lh node_modules/electron/dist/electron 2>/dev/null || echo MISSING)"
echo "dist-win/electron.exe: $(ls -lh node_modules/electron/dist-win/electron.exe 2>/dev/null || echo MISSING)"
echo "path.txt: $(cat node_modules/electron/path.txt 2>/dev/null || echo MISSING)"
- name: Build source - name: Build source
if: steps.version-check.outputs.SKIP == 'false' if: steps.version-check.outputs.SKIP == 'false'
run: npm run build run: npm run build
@@ -80,7 +68,7 @@ jobs:
- name: Build Linux distributables - name: Build Linux distributables
if: steps.version-check.outputs.SKIP == 'false' if: steps.version-check.outputs.SKIP == 'false'
run: npx electron-builder --linux -c.electronDist=node_modules/electron/dist --publish never run: npx electron-builder --linux -c.electronDist=node_modules/electron/dist-linux --publish never
- name: Report build sizes - name: Report build sizes
if: steps.version-check.outputs.SKIP == 'false' if: steps.version-check.outputs.SKIP == 'false'
+71 -55
View File
@@ -1,13 +1,15 @@
'use strict'; 'use strict';
/** /**
* Downloads the patched Electron build and extracts it into node_modules/electron/dist/. * Downloads patched Electron builds for Windows (v42) and Linux (v43).
* *
* The patched Electron fixes input starvation ("aim freeze") when --disable-frame-rate-limit * The patched Electron fixes input starvation ("aim freeze") when --disable-frame-rate-limit
* is active on modern Chromium. Without this, uncapped FPS causes 50-300ms input delays. * is active on modern Chromium. Without this, uncapped FPS causes 50-300ms input delays.
* *
* The zip is hosted as a GitHub release asset. The script checks the * Platform behavior:
* local version file to skip re-downloading if already present. * Windows: patched Win → dist/ (replaces stock)
* Linux (local): patched Linux → dist/ (replaces stock), Win → dist-win/
* CI (Linux): Win → dist-win/, Linux → dist-linux/ (stock stays in dist/)
* *
* Usage: * Usage:
* node scripts/download-electron.js # download if needed * node scripts/download-electron.js # download if needed
@@ -21,25 +23,18 @@ const path = require('path');
const { execSync } = require('child_process'); const { execSync } = require('child_process');
// ── Configuration ────────────────────────────────────────────────────────── // ── Configuration ──────────────────────────────────────────────────────────
const ELECTRON_VERSION = '42.0.0-nightly.20260227';
const ASSET_NAME = 'electron-v42.0.0-nightly-release-patched-win32-x64.zip';
const GITHUB_BASE = 'https://github.com'; const GITHUB_BASE = 'https://github.com';
const REPO = 'bigjakk/Electron-Websocket-Fix'; const REPO = 'bigjakk/Electron-Websocket-Fix';
const RELEASE_TAG = 'v1.0.0'; const RELEASE_TAG = 'v1.0.0';
const DIRECT_DOWNLOAD_URL = `${GITHUB_BASE}/${REPO}/releases/download/${RELEASE_TAG}/${ASSET_NAME}`;
// On Windows, overwrite the npm-installed Electron with our patched build. const PLATFORMS = {
// On Linux/macOS (CI cross-compilation), extract to a separate dist-win/ directory win32: { asset: 'electron-v42.0.0-nightly-release-patched-win32-x64.zip' },
// so the npm-installed platform-native Electron stays in dist/ for bytenode compilation. linux: { asset: 'electron-v43.0.0-nightly-release-patched-linux-x64.zip' },
};
const IS_WIN = process.platform === 'win32'; const IS_WIN = process.platform === 'win32';
const ELECTRON_DIST = IS_WIN const IS_CI = !!process.env.CI;
? path.resolve(__dirname, '..', 'node_modules', 'electron', 'dist') const ELECTRON_BASE = path.resolve(__dirname, '..', 'node_modules', 'electron');
: path.resolve(__dirname, '..', 'node_modules', 'electron', 'dist-win');
const VERSION_FILE = path.join(ELECTRON_DIST, 'version');
// Separate marker file to distinguish patched from stock electron-nightly.
// Both have the same version string, so VERSION_FILE alone is not sufficient.
const PATCHED_MARKER = path.join(ELECTRON_DIST, '.patched');
const TEMP_ZIP = path.join(ELECTRON_DIST, '..', '_electron-patched.zip');
// ── Helpers ──────────────────────────────────────────────────────────────── // ── Helpers ────────────────────────────────────────────────────────────────
@@ -95,10 +90,6 @@ function downloadToFile(url, dest) {
}); });
} }
function getAssetUrl() {
return DIRECT_DOWNLOAD_URL;
}
function extractZip(zipPath, destDir) { function extractZip(zipPath, destDir) {
// Use PowerShell on Windows, unzip on Linux/macOS // Use PowerShell on Windows, unzip on Linux/macOS
if (process.platform === 'win32') { if (process.platform === 'win32') {
@@ -111,68 +102,93 @@ function extractZip(zipPath, destDir) {
} }
} }
// ── Main ─────────────────────────────────────────────────────────────────── // ── Per-directory install ──────────────────────────────────────────────────
async function main() { async function installTo(distDir, platform) {
const force = process.argv.includes('--force'); const force = process.argv.includes('--force');
const patchedMarker = path.join(distDir, '.patched');
const tempZip = path.join(ELECTRON_BASE, `_electron-patched-${platform.asset}`);
const label = path.relative(path.resolve(__dirname, '..'), distDir);
// Check if patched version is already installed. // Check if this exact asset is already installed.
// The .patched marker distinguishes our build from stock electron-nightly // The marker stores the asset filename to handle version changes.
// (both share the same version string). if (!force && fs.existsSync(patchedMarker)) {
if (!force && fs.existsSync(PATCHED_MARKER)) { const installed = fs.readFileSync(patchedMarker, 'utf8').trim();
const installed = fs.readFileSync(PATCHED_MARKER, 'utf8').trim(); if (installed === platform.asset) {
if (installed === ELECTRON_VERSION) { console.log(` [${label}] ${platform.asset} already installed, skipping`);
console.log(` Patched Electron ${ELECTRON_VERSION} already installed, skipping`);
console.log(' (use --force to re-download)');
return; return;
} }
console.log(` Installed: ${installed}, need: ${ELECTRON_VERSION}`); console.log(` [${label}] Installed: ${installed}, need: ${platform.asset}`);
} }
// Direct download from GitHub release // Direct download from GitHub release
const url = getAssetUrl(); const url = `${GITHUB_BASE}/${REPO}/releases/download/${RELEASE_TAG}/${platform.asset}`;
console.log(` Asset URL: ${url}`); console.log(` [${label}] Asset URL: ${url}`);
// Download // Download
await downloadToFile(url, TEMP_ZIP); await downloadToFile(url, tempZip);
const zipSize = (fs.statSync(TEMP_ZIP).size / 1048576).toFixed(1); const zipSize = (fs.statSync(tempZip).size / 1048576).toFixed(1);
console.log(` Downloaded: ${zipSize} MB`); console.log(` [${label}] Downloaded: ${zipSize} MB`);
// Clear existing target dir and extract // Clear existing target dir and extract
console.log(` Extracting to ${path.relative(path.resolve(__dirname, '..'), ELECTRON_DIST)}/...`); console.log(` [${label}] Extracting...`);
if (fs.existsSync(ELECTRON_DIST)) { if (fs.existsSync(distDir)) {
fs.rmSync(ELECTRON_DIST, { recursive: true, force: true }); fs.rmSync(distDir, { recursive: true, force: true });
} }
fs.mkdirSync(ELECTRON_DIST, { recursive: true }); fs.mkdirSync(distDir, { recursive: true });
extractZip(TEMP_ZIP, ELECTRON_DIST); extractZip(tempZip, distDir);
// Clean up temp zip // Clean up temp zip
fs.unlinkSync(TEMP_ZIP); fs.unlinkSync(tempZip);
// Write marker with asset name for future skip-check
fs.writeFileSync(patchedMarker, platform.asset);
const versionFile = path.join(distDir, 'version');
if (fs.existsSync(versionFile)) {
const ver = fs.readFileSync(versionFile, 'utf8').trim();
console.log(` [${label}] Installed patched Electron ${ver}`);
} else {
console.log(` [${label}] Installed ${platform.asset} (no version file)`);
}
}
// ── Main ───────────────────────────────────────────────────────────────────
async function main() {
if (IS_WIN) {
// Windows local dev: patched Win → dist/ (replaces stock)
await installTo(path.join(ELECTRON_BASE, 'dist'), PLATFORMS.win32);
} else if (IS_CI) {
// CI (Linux): keep stock in dist/ untouched,
// patched Win → dist-win/, patched Linux → dist-linux/
await installTo(path.join(ELECTRON_BASE, 'dist-win'), PLATFORMS.win32);
await installTo(path.join(ELECTRON_BASE, 'dist-linux'), PLATFORMS.linux);
} else {
// Linux local dev: patched Linux → dist/ (for npm run dev),
// patched Win → dist-win/ (for cross-compilation)
await installTo(path.join(ELECTRON_BASE, 'dist'), PLATFORMS.linux);
await installTo(path.join(ELECTRON_BASE, 'dist-win'), PLATFORMS.win32);
}
// Write path.txt so the electron package's lazy downloader (index.js) // Write path.txt so the electron package's lazy downloader (index.js)
// considers the binary already installed and doesn't re-download stock. // considers the binary already installed and doesn't re-download stock.
const platformExe = IS_WIN ? 'electron.exe' : 'electron'; const platformExe = IS_WIN ? 'electron.exe' : 'electron';
fs.writeFileSync(path.join(ELECTRON_DIST, '..', 'path.txt'), platformExe); fs.writeFileSync(path.join(ELECTRON_BASE, 'path.txt'), platformExe);
// Write marker and verify
if (fs.existsSync(VERSION_FILE)) {
const ver = fs.readFileSync(VERSION_FILE, 'utf8').trim();
fs.writeFileSync(PATCHED_MARKER, ver);
console.log(` Installed patched Electron ${ver}`);
} else {
console.log(' Warning: version file not found after extraction');
}
} }
console.log('[KCC] Setting up patched Electron...'); console.log('[KCC] Setting up patched Electron...');
main().then(() => { main().then(() => {
console.log('[KCC] Patched Electron ready.'); console.log('[KCC] Patched Electron ready.');
if (!IS_WIN) {
console.log(' (use --force to re-download)');
}
}).catch((err) => { }).catch((err) => {
console.error('[KCC] Electron download failed:', err.message); console.error('[KCC] Electron download failed:', err.message);
console.error(''); console.error('');
console.error(' Download the patched Electron manually from:'); console.error(' Download the patched Electron manually from:');
console.error(` ${DIRECT_DOWNLOAD_URL}`); console.error(` ${GITHUB_BASE}/${REPO}/releases/tag/${RELEASE_TAG}`);
console.error(''); console.error('');
console.error(` See ${GITHUB_BASE}/${REPO} for details.`); console.error(` Win asset: ${PLATFORMS.win32.asset}`);
console.error(` Linux asset: ${PLATFORMS.linux.asset}`);
process.exit(1); process.exit(1);
}); });