mirror of
https://github.com/plebbit/seedit.git
synced 2026-02-05 11:30:59 -05:00
Migrated build system from electron-builder to Electron Forge with new configuration in forge.config.js. Replaced manual IPFS binary downloads with kubo npm package, updating start-ipfs.js to resolve binaries from node_modules. Simplified CI workflows to use new build scripts and verification helpers. Added scripts to find and verify executables in Forge output directory.
137 lines
3.3 KiB
JavaScript
137 lines
3.3 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Verify that a packaged Electron executable starts correctly.
|
|
* This script launches the executable and checks that the RPC port (9138) becomes available.
|
|
*/
|
|
|
|
import { spawn } from 'child_process';
|
|
import { existsSync } from 'fs';
|
|
import { createServer } from 'net';
|
|
|
|
const executablePath = process.argv[2];
|
|
const rpcPort = 9138;
|
|
const timeout = 30000; // 30 seconds
|
|
|
|
if (!executablePath) {
|
|
console.error('Usage: node scripts/verify-executable.js <executable-path>');
|
|
process.exit(1);
|
|
}
|
|
|
|
if (!existsSync(executablePath)) {
|
|
console.error(`Error: Executable not found: ${executablePath}`);
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log(`Starting executable: ${executablePath}`);
|
|
console.log(`Checking for RPC port ${rpcPort}...`);
|
|
|
|
// Start the executable
|
|
const appProcess = spawn(executablePath, [], {
|
|
detached: false,
|
|
stdio: 'pipe',
|
|
});
|
|
|
|
let appExited = false;
|
|
let portAvailable = false;
|
|
let timeoutId;
|
|
|
|
// Check if port is in use (app is running)
|
|
function checkPort() {
|
|
return new Promise((resolve) => {
|
|
const server = createServer();
|
|
server.listen(rpcPort, '127.0.0.1', () => {
|
|
server.close();
|
|
resolve(false); // Port is available (not in use yet)
|
|
});
|
|
server.on('error', (err) => {
|
|
if (err.code === 'EADDRINUSE') {
|
|
resolve(true); // Port is in use (app is running - success!)
|
|
} else {
|
|
resolve(false);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
// Monitor app process
|
|
appProcess.on('exit', (code, signal) => {
|
|
appExited = true;
|
|
if (code !== null && code !== 0) {
|
|
console.error(`App exited with code ${code}`);
|
|
cleanup();
|
|
process.exit(1);
|
|
}
|
|
});
|
|
|
|
appProcess.stderr.on('data', (data) => {
|
|
const text = data.toString();
|
|
// Filter out common harmless errors
|
|
if (!text.includes('Gtk') && !text.includes('libnotify')) {
|
|
console.error('stderr:', text);
|
|
}
|
|
});
|
|
|
|
// Poll for port availability
|
|
async function pollPort() {
|
|
const maxAttempts = 30; // 30 attempts over 30 seconds
|
|
let attempts = 0;
|
|
|
|
const interval = setInterval(async () => {
|
|
attempts++;
|
|
const inUse = await checkPort();
|
|
|
|
if (inUse) {
|
|
portAvailable = true;
|
|
console.log(`✓ RPC port ${rpcPort} is in use (app is running)`);
|
|
clearInterval(interval);
|
|
clearTimeout(timeoutId);
|
|
cleanup();
|
|
process.exit(0);
|
|
}
|
|
|
|
if (attempts >= maxAttempts || appExited) {
|
|
clearInterval(interval);
|
|
clearTimeout(timeoutId);
|
|
if (!portAvailable) {
|
|
console.error(`✗ RPC port ${rpcPort} did not become available within ${timeout / 1000} seconds`);
|
|
cleanup();
|
|
process.exit(1);
|
|
}
|
|
}
|
|
}, 1000);
|
|
}
|
|
|
|
// Set overall timeout
|
|
timeoutId = setTimeout(() => {
|
|
if (!portAvailable) {
|
|
console.error(`✗ Timeout: RPC port ${rpcPort} did not become available within ${timeout / 1000} seconds`);
|
|
cleanup();
|
|
process.exit(1);
|
|
}
|
|
}, timeout);
|
|
|
|
function cleanup() {
|
|
try {
|
|
if (appProcess && !appProcess.killed) {
|
|
appProcess.kill();
|
|
// Also try to kill any child processes
|
|
if (appProcess.pid) {
|
|
try {
|
|
process.kill(appProcess.pid, 'SIGTERM');
|
|
} catch (e) {
|
|
// Ignore errors
|
|
}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
// Ignore cleanup errors
|
|
}
|
|
}
|
|
|
|
// Handle process termination
|
|
process.on('SIGINT', cleanup);
|
|
process.on('SIGTERM', cleanup);
|
|
|
|
// Start polling
|
|
pollPort();
|