Files

191 lines
5.9 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
/**
* Server Manager Script for Maven Integration
* Handles starting and stopping the React development server
*/
const { spawn, exec } = require('child_process');
const fs = require('fs');
const path = require('path');
const PID_FILE = path.join(__dirname, '..', '.react-server.pid');
const PORT = process.env.PORT || 3001;
function writePidFile(pid) {
fs.writeFileSync(PID_FILE, pid.toString());
}
function readPidFile() {
try {
return fs.readFileSync(PID_FILE, 'utf8').trim();
} catch (error) {
return null;
}
}
function deletePidFile() {
try {
fs.unlinkSync(PID_FILE);
} catch (error) {
// Ignore if file doesn't exist
}
}
function isServerRunning(pid) {
try {
process.kill(pid, 0);
return true;
} catch (error) {
return false;
}
}
function waitForServer(maxAttempts = 30, interval = 1000) {
return new Promise((resolve, reject) => {
let attempts = 0;
// Detect CI environment for different behavior
const isCI = process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true' || process.env.QQQ_SELENIUM_HEADLESS === 'true';
if (isCI) {
console.log('🔍 CI environment detected - using extended server wait parameters');
maxAttempts = Math.max(maxAttempts, 60); // Minimum 60 attempts in CI
interval = Math.max(interval, 2000); // Minimum 2 second intervals in CI
}
const checkServer = () => {
attempts++;
// Use curl to check if server is ready (more reliable for HTTPS)
const { exec } = require('child_process');
const curlCommand = `curl -k -s -o /dev/null -w "%{http_code}" https://localhost:${PORT}`;
exec(curlCommand, (error, stdout, stderr) => {
if (stdout && stdout.trim() !== '000') {
console.log(`✅ React server is ready on port ${PORT} (HTTP ${stdout.trim()}) after ${attempts} attempts`);
resolve();
} else if (attempts >= maxAttempts) {
reject(new Error(`Server failed to start after ${maxAttempts} attempts (${maxAttempts * interval / 1000} seconds)`));
} else {
// Log every 5th attempt, or every attempt in CI
if (attempts % 5 === 0 || isCI) {
console.log(`⏳ Waiting for React server on port ${PORT}... (attempt ${attempts}/${maxAttempts})`);
if (isCI && attempts > 10) {
console.log(` Error details: ${error ? error.message : 'Connection refused'}`);
}
}
setTimeout(checkServer, interval);
}
});
};
checkServer();
});
}
function startServer() {
console.log('🚀 Starting React development server...');
// Detect CI environment for different behavior
const isCI = process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true' || process.env.QQQ_SELENIUM_HEADLESS === 'true';
if (isCI) {
console.log('🔍 CI environment detected - using enhanced startup process');
}
// Start the server in the background and exit immediately
const child = spawn('npm', ['start'], {
stdio: 'ignore', // Don't capture output - let it run independently
detached: true, // Detach from parent process
env: {
...process.env,
BROWSER: 'none',
PORT: PORT,
HTTPS: 'true',
GENERATE_SOURCEMAP: 'false',
FAST_REFRESH: 'false'
}
});
writePidFile(child.pid);
console.log(`📋 Server PID: ${child.pid}`);
console.log('🚀 React server started in background');
// Unref so parent can exit without killing child
child.unref();
// Exit immediately - server runs in background
process.exit(0);
}
function stopServer() {
console.log('🛑 Stopping React development server...');
const pid = readPidFile();
if (pid && isServerRunning(pid)) {
try {
process.kill(pid, 'SIGTERM');
console.log(`✅ Stopped server (PID: ${pid})`);
} catch (error) {
console.error('❌ Failed to stop server:', error.message);
}
} else {
console.log('ℹ️ No running server found');
}
deletePidFile();
}
function waitForServerOnly() {
console.log('⏳ Waiting for React server to be ready...');
const isCI = process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true' || process.env.QQQ_SELENIUM_HEADLESS === 'true';
const maxAttempts = isCI ? 60 : 30;
const interval = isCI ? 2000 : 1000;
if (isCI) {
console.log('🔍 CI environment detected - using extended wait parameters');
}
waitForServer(maxAttempts, interval)
.then(() => {
console.log('✅ React server is ready for integration tests');
process.exit(0);
})
.catch((error) => {
console.error('❌ Server wait failed:', error.message);
process.exit(1);
});
}
// Handle command line arguments
const command = process.argv[2];
switch (command) {
case 'start':
startServer();
break;
case 'stop':
stopServer();
break;
case 'wait':
waitForServerOnly();
break;
default:
console.log('Usage: node server-manager.js [start|stop|wait]');
process.exit(1);
}
// Handle process termination
process.on('SIGINT', () => {
console.log('\n🛑 Received SIGINT, stopping server...');
stopServer();
process.exit(0);
});
process.on('SIGTERM', () => {
console.log('\n🛑 Received SIGTERM, stopping server...');
stopServer();
process.exit(0);
});