feat(ci): use patched Linux Electron from GitHub release
Build and Release / build-and-release (push) Failing after 3m51s
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:
@@ -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'
|
||||||
|
|||||||
+194
-178
@@ -1,178 +1,194 @@
|
|||||||
'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/
|
||||||
* Usage:
|
* CI (Linux): Win → dist-win/, Linux → dist-linux/ (stock stays in dist/)
|
||||||
* node scripts/download-electron.js # download if needed
|
*
|
||||||
* node scripts/download-electron.js --force # re-download even if present
|
* Usage:
|
||||||
*/
|
* node scripts/download-electron.js # download if needed
|
||||||
|
* node scripts/download-electron.js --force # re-download even if present
|
||||||
const https = require('https');
|
*/
|
||||||
const http = require('http');
|
|
||||||
const fs = require('fs');
|
const https = require('https');
|
||||||
const path = require('path');
|
const http = require('http');
|
||||||
const { execSync } = require('child_process');
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
// ── Configuration ──────────────────────────────────────────────────────────
|
const { execSync } = require('child_process');
|
||||||
const ELECTRON_VERSION = '42.0.0-nightly.20260227';
|
|
||||||
const ASSET_NAME = 'electron-v42.0.0-nightly-release-patched-win32-x64.zip';
|
// ── Configuration ──────────────────────────────────────────────────────────
|
||||||
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}`;
|
|
||||||
|
const PLATFORMS = {
|
||||||
// On Windows, overwrite the npm-installed Electron with our patched build.
|
win32: { asset: 'electron-v42.0.0-nightly-release-patched-win32-x64.zip' },
|
||||||
// On Linux/macOS (CI cross-compilation), extract to a separate dist-win/ directory
|
linux: { asset: 'electron-v43.0.0-nightly-release-patched-linux-x64.zip' },
|
||||||
// so the npm-installed platform-native Electron stays in dist/ for bytenode compilation.
|
};
|
||||||
const IS_WIN = process.platform === 'win32';
|
|
||||||
const ELECTRON_DIST = IS_WIN
|
const IS_WIN = process.platform === 'win32';
|
||||||
? path.resolve(__dirname, '..', 'node_modules', 'electron', 'dist')
|
const IS_CI = !!process.env.CI;
|
||||||
: path.resolve(__dirname, '..', 'node_modules', 'electron', 'dist-win');
|
const ELECTRON_BASE = path.resolve(__dirname, '..', 'node_modules', 'electron');
|
||||||
const VERSION_FILE = path.join(ELECTRON_DIST, 'version');
|
|
||||||
// Separate marker file to distinguish patched from stock electron-nightly.
|
// ── Helpers ────────────────────────────────────────────────────────────────
|
||||||
// Both have the same version string, so VERSION_FILE alone is not sufficient.
|
|
||||||
const PATCHED_MARKER = path.join(ELECTRON_DIST, '.patched');
|
function get(url) {
|
||||||
const TEMP_ZIP = path.join(ELECTRON_DIST, '..', '_electron-patched.zip');
|
const lib = url.startsWith('https') ? https : http;
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
// ── Helpers ────────────────────────────────────────────────────────────────
|
lib.get(url, { headers: { 'User-Agent': 'KCC-Build' } }, (res) => {
|
||||||
|
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
||||||
function get(url) {
|
get(res.headers.location).then(resolve, reject);
|
||||||
const lib = url.startsWith('https') ? https : http;
|
res.resume();
|
||||||
return new Promise((resolve, reject) => {
|
return;
|
||||||
lib.get(url, { headers: { 'User-Agent': 'KCC-Build' } }, (res) => {
|
}
|
||||||
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
if (res.statusCode !== 200) {
|
||||||
get(res.headers.location).then(resolve, reject);
|
res.resume();
|
||||||
res.resume();
|
reject(new Error(`HTTP ${res.statusCode} for ${url}`));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (res.statusCode !== 200) {
|
resolve(res);
|
||||||
res.resume();
|
}).on('error', reject);
|
||||||
reject(new Error(`HTTP ${res.statusCode} for ${url}`));
|
});
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
resolve(res);
|
function downloadToFile(url, dest) {
|
||||||
}).on('error', reject);
|
return new Promise(async (resolve, reject) => {
|
||||||
});
|
try {
|
||||||
}
|
const res = await get(url);
|
||||||
|
const total = parseInt(res.headers['content-length'] || '0', 10);
|
||||||
function downloadToFile(url, dest) {
|
let downloaded = 0;
|
||||||
return new Promise(async (resolve, reject) => {
|
|
||||||
try {
|
const file = fs.createWriteStream(dest);
|
||||||
const res = await get(url);
|
res.on('data', (chunk) => {
|
||||||
const total = parseInt(res.headers['content-length'] || '0', 10);
|
downloaded += chunk.length;
|
||||||
let downloaded = 0;
|
if (total > 0) {
|
||||||
|
const pct = ((downloaded / total) * 100).toFixed(1);
|
||||||
const file = fs.createWriteStream(dest);
|
const mb = (downloaded / 1048576).toFixed(1);
|
||||||
res.on('data', (chunk) => {
|
const totalMb = (total / 1048576).toFixed(1);
|
||||||
downloaded += chunk.length;
|
process.stdout.write(`\r Downloading: ${pct}% (${mb}/${totalMb} MB)`);
|
||||||
if (total > 0) {
|
}
|
||||||
const pct = ((downloaded / total) * 100).toFixed(1);
|
});
|
||||||
const mb = (downloaded / 1048576).toFixed(1);
|
res.pipe(file);
|
||||||
const totalMb = (total / 1048576).toFixed(1);
|
file.on('finish', () => {
|
||||||
process.stdout.write(`\r Downloading: ${pct}% (${mb}/${totalMb} MB)`);
|
file.close();
|
||||||
}
|
process.stdout.write('\n');
|
||||||
});
|
resolve();
|
||||||
res.pipe(file);
|
});
|
||||||
file.on('finish', () => {
|
file.on('error', (err) => {
|
||||||
file.close();
|
fs.unlinkSync(dest);
|
||||||
process.stdout.write('\n');
|
reject(err);
|
||||||
resolve();
|
});
|
||||||
});
|
} catch (err) {
|
||||||
file.on('error', (err) => {
|
reject(err);
|
||||||
fs.unlinkSync(dest);
|
}
|
||||||
reject(err);
|
});
|
||||||
});
|
}
|
||||||
} catch (err) {
|
|
||||||
reject(err);
|
function extractZip(zipPath, destDir) {
|
||||||
}
|
// Use PowerShell on Windows, unzip on Linux/macOS
|
||||||
});
|
if (process.platform === 'win32') {
|
||||||
}
|
execSync(
|
||||||
|
`powershell -NoProfile -Command "Expand-Archive -Force -Path '${zipPath}' -DestinationPath '${destDir}'"`,
|
||||||
function getAssetUrl() {
|
{ stdio: 'inherit' }
|
||||||
return DIRECT_DOWNLOAD_URL;
|
);
|
||||||
}
|
} else {
|
||||||
|
execSync(`unzip -o "${zipPath}" -d "${destDir}"`, { stdio: 'inherit' });
|
||||||
function extractZip(zipPath, destDir) {
|
}
|
||||||
// Use PowerShell on Windows, unzip on Linux/macOS
|
}
|
||||||
if (process.platform === 'win32') {
|
|
||||||
execSync(
|
// ── Per-directory install ──────────────────────────────────────────────────
|
||||||
`powershell -NoProfile -Command "Expand-Archive -Force -Path '${zipPath}' -DestinationPath '${destDir}'"`,
|
|
||||||
{ stdio: 'inherit' }
|
async function installTo(distDir, platform) {
|
||||||
);
|
const force = process.argv.includes('--force');
|
||||||
} else {
|
const patchedMarker = path.join(distDir, '.patched');
|
||||||
execSync(`unzip -o "${zipPath}" -d "${destDir}"`, { stdio: 'inherit' });
|
const tempZip = path.join(ELECTRON_BASE, `_electron-patched-${platform.asset}`);
|
||||||
}
|
const label = path.relative(path.resolve(__dirname, '..'), distDir);
|
||||||
}
|
|
||||||
|
// Check if this exact asset is already installed.
|
||||||
// ── Main ───────────────────────────────────────────────────────────────────
|
// The marker stores the asset filename to handle version changes.
|
||||||
|
if (!force && fs.existsSync(patchedMarker)) {
|
||||||
async function main() {
|
const installed = fs.readFileSync(patchedMarker, 'utf8').trim();
|
||||||
const force = process.argv.includes('--force');
|
if (installed === platform.asset) {
|
||||||
|
console.log(` [${label}] ${platform.asset} already installed, skipping`);
|
||||||
// Check if patched version is already installed.
|
return;
|
||||||
// The .patched marker distinguishes our build from stock electron-nightly
|
}
|
||||||
// (both share the same version string).
|
console.log(` [${label}] Installed: ${installed}, need: ${platform.asset}`);
|
||||||
if (!force && fs.existsSync(PATCHED_MARKER)) {
|
}
|
||||||
const installed = fs.readFileSync(PATCHED_MARKER, 'utf8').trim();
|
|
||||||
if (installed === ELECTRON_VERSION) {
|
// Direct download from GitHub release
|
||||||
console.log(` Patched Electron ${ELECTRON_VERSION} already installed, skipping`);
|
const url = `${GITHUB_BASE}/${REPO}/releases/download/${RELEASE_TAG}/${platform.asset}`;
|
||||||
console.log(' (use --force to re-download)');
|
console.log(` [${label}] Asset URL: ${url}`);
|
||||||
return;
|
|
||||||
}
|
// Download
|
||||||
console.log(` Installed: ${installed}, need: ${ELECTRON_VERSION}`);
|
await downloadToFile(url, tempZip);
|
||||||
}
|
const zipSize = (fs.statSync(tempZip).size / 1048576).toFixed(1);
|
||||||
|
console.log(` [${label}] Downloaded: ${zipSize} MB`);
|
||||||
// Direct download from GitHub release
|
|
||||||
const url = getAssetUrl();
|
// Clear existing target dir and extract
|
||||||
console.log(` Asset URL: ${url}`);
|
console.log(` [${label}] Extracting...`);
|
||||||
|
if (fs.existsSync(distDir)) {
|
||||||
// Download
|
fs.rmSync(distDir, { recursive: true, force: true });
|
||||||
await downloadToFile(url, TEMP_ZIP);
|
}
|
||||||
const zipSize = (fs.statSync(TEMP_ZIP).size / 1048576).toFixed(1);
|
fs.mkdirSync(distDir, { recursive: true });
|
||||||
console.log(` Downloaded: ${zipSize} MB`);
|
extractZip(tempZip, distDir);
|
||||||
|
|
||||||
// Clear existing target dir and extract
|
// Clean up temp zip
|
||||||
console.log(` Extracting to ${path.relative(path.resolve(__dirname, '..'), ELECTRON_DIST)}/...`);
|
fs.unlinkSync(tempZip);
|
||||||
if (fs.existsSync(ELECTRON_DIST)) {
|
|
||||||
fs.rmSync(ELECTRON_DIST, { recursive: true, force: true });
|
// Write marker with asset name for future skip-check
|
||||||
}
|
fs.writeFileSync(patchedMarker, platform.asset);
|
||||||
fs.mkdirSync(ELECTRON_DIST, { recursive: true });
|
const versionFile = path.join(distDir, 'version');
|
||||||
extractZip(TEMP_ZIP, ELECTRON_DIST);
|
if (fs.existsSync(versionFile)) {
|
||||||
|
const ver = fs.readFileSync(versionFile, 'utf8').trim();
|
||||||
// Clean up temp zip
|
console.log(` [${label}] Installed patched Electron ${ver}`);
|
||||||
fs.unlinkSync(TEMP_ZIP);
|
} else {
|
||||||
|
console.log(` [${label}] Installed ${platform.asset} (no version file)`);
|
||||||
// Write path.txt so the electron package's lazy downloader (index.js)
|
}
|
||||||
// considers the binary already installed and doesn't re-download stock.
|
}
|
||||||
const platformExe = IS_WIN ? 'electron.exe' : 'electron';
|
|
||||||
fs.writeFileSync(path.join(ELECTRON_DIST, '..', 'path.txt'), platformExe);
|
// ── Main ───────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
// Write marker and verify
|
async function main() {
|
||||||
if (fs.existsSync(VERSION_FILE)) {
|
if (IS_WIN) {
|
||||||
const ver = fs.readFileSync(VERSION_FILE, 'utf8').trim();
|
// Windows local dev: patched Win → dist/ (replaces stock)
|
||||||
fs.writeFileSync(PATCHED_MARKER, ver);
|
await installTo(path.join(ELECTRON_BASE, 'dist'), PLATFORMS.win32);
|
||||||
console.log(` Installed patched Electron ${ver}`);
|
} else if (IS_CI) {
|
||||||
} else {
|
// CI (Linux): keep stock in dist/ untouched,
|
||||||
console.log(' Warning: version file not found after extraction');
|
// 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 {
|
||||||
console.log('[KCC] Setting up patched Electron...');
|
// Linux local dev: patched Linux → dist/ (for npm run dev),
|
||||||
main().then(() => {
|
// patched Win → dist-win/ (for cross-compilation)
|
||||||
console.log('[KCC] Patched Electron ready.');
|
await installTo(path.join(ELECTRON_BASE, 'dist'), PLATFORMS.linux);
|
||||||
}).catch((err) => {
|
await installTo(path.join(ELECTRON_BASE, 'dist-win'), PLATFORMS.win32);
|
||||||
console.error('[KCC] Electron download failed:', err.message);
|
}
|
||||||
console.error('');
|
|
||||||
console.error(' Download the patched Electron manually from:');
|
// Write path.txt so the electron package's lazy downloader (index.js)
|
||||||
console.error(` ${DIRECT_DOWNLOAD_URL}`);
|
// considers the binary already installed and doesn't re-download stock.
|
||||||
console.error('');
|
const platformExe = IS_WIN ? 'electron.exe' : 'electron';
|
||||||
console.error(` See ${GITHUB_BASE}/${REPO} for details.`);
|
fs.writeFileSync(path.join(ELECTRON_BASE, 'path.txt'), platformExe);
|
||||||
process.exit(1);
|
}
|
||||||
});
|
|
||||||
|
console.log('[KCC] Setting up patched Electron...');
|
||||||
|
main().then(() => {
|
||||||
|
console.log('[KCC] Patched Electron ready.');
|
||||||
|
if (!IS_WIN) {
|
||||||
|
console.log(' (use --force to re-download)');
|
||||||
|
}
|
||||||
|
}).catch((err) => {
|
||||||
|
console.error('[KCC] Electron download failed:', err.message);
|
||||||
|
console.error('');
|
||||||
|
console.error(' Download the patched Electron manually from:');
|
||||||
|
console.error(` ${GITHUB_BASE}/${REPO}/releases/tag/${RELEASE_TAG}`);
|
||||||
|
console.error('');
|
||||||
|
console.error(` Win asset: ${PLATFORMS.win32.asset}`);
|
||||||
|
console.error(` Linux asset: ${PLATFORMS.linux.asset}`);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user