Skip to content

Commit 3f42d31

Browse files
fix: implement more aggressive port cleanup for federated-css tests
- Created aggressive-port-cleanup script that uses multiple methods to kill ports - Uses lsof on macOS/Linux to forcefully kill processes on ports - Increased delays between cleanup attempts to ensure ports are released - Updated both federated-css and federated-css-react-ssr to use more robust cleanup This should resolve persistent EADDRINUSE errors in CI environments
1 parent ef990e6 commit 3f42d31

File tree

5 files changed

+104
-45
lines changed

5 files changed

+104
-45
lines changed

federated-css-react-ssr/scripts/start-exposes.cjs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,18 @@ async function main() {
3636
{ dir: 'expose-less', port: 3007 },
3737
];
3838

39-
// Clean up all ports first
39+
// Clean up all ports first with more aggressive approach
4040
console.log('[exposes] cleaning up ports...');
41-
await Promise.all(exposes.map(({ port }) => killPort(port)));
42-
await new Promise(resolve => setTimeout(resolve, 1000));
41+
for (const { port } of exposes) {
42+
await killPort(port);
43+
// Additional cleanup attempt
44+
try {
45+
await killPort(port);
46+
} catch (e) {
47+
// Ignore
48+
}
49+
}
50+
await new Promise(resolve => setTimeout(resolve, 3000));
4351

4452
const procs = [];
4553
for (const { dir, port } of exposes) {

federated-css-react-ssr/scripts/start-shells.cjs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,18 @@ async function main() {
3535
{ dir: 'scss-tailwind-css', port: 4005 },
3636
];
3737

38-
// Clean up all ports first
38+
// Clean up all ports first with more aggressive approach
3939
console.log('[shells] cleaning up ports...');
40-
await Promise.all(shells.map(({ port }) => killPort(port)));
41-
await new Promise(resolve => setTimeout(resolve, 1000));
40+
for (const { port } of shells) {
41+
await killPort(port);
42+
// Additional cleanup attempt
43+
try {
44+
await killPort(port);
45+
} catch (e) {
46+
// Ignore
47+
}
48+
}
49+
await new Promise(resolve => setTimeout(resolve, 3000));
4250

4351
const procs = [];
4452
for (const { dir, port } of shells) {
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
const { execSync } = require('child_process');
2+
const kill = require('kill-port');
3+
4+
async function aggressiveKillPort(port) {
5+
console.log(`[aggressive-cleanup] Killing port ${port}...`);
6+
7+
// Try kill-port first
8+
try {
9+
await kill(port, 'tcp');
10+
} catch (e) {
11+
// Ignore
12+
}
13+
14+
// Also try system commands
15+
try {
16+
if (process.platform === 'darwin' || process.platform === 'linux') {
17+
// Find and kill process using lsof
18+
execSync(`lsof -ti:${port} | xargs kill -9`, { stdio: 'ignore' });
19+
}
20+
} catch (e) {
21+
// Ignore if no process found
22+
}
23+
24+
// Final attempt with fuser (Linux)
25+
try {
26+
if (process.platform === 'linux') {
27+
execSync(`fuser -k ${port}/tcp`, { stdio: 'ignore' });
28+
}
29+
} catch (e) {
30+
// Ignore
31+
}
32+
}
33+
34+
async function cleanupAllPorts() {
35+
const reactConsumerPorts = [3001, 3002, 3003, 3004, 3005, 3006, 3007];
36+
const exposePorts = [4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007];
37+
const nextConsumerPorts = [8081, 8082, 8083, 8084];
38+
39+
const allPorts = [...reactConsumerPorts, ...exposePorts, ...nextConsumerPorts];
40+
41+
console.log('[aggressive-cleanup] Starting aggressive port cleanup...');
42+
43+
// Kill all ports multiple times with delays
44+
for (let attempt = 1; attempt <= 3; attempt++) {
45+
console.log(`[aggressive-cleanup] Attempt ${attempt}...`);
46+
for (const port of allPorts) {
47+
await aggressiveKillPort(port);
48+
}
49+
if (attempt < 3) {
50+
await new Promise(resolve => setTimeout(resolve, 2000));
51+
}
52+
}
53+
54+
console.log('[aggressive-cleanup] All ports aggressively cleaned.');
55+
}
56+
57+
// Run if called directly
58+
if (require.main === module) {
59+
cleanupAllPorts().catch(err => {
60+
console.error('[aggressive-cleanup] Error:', err);
61+
process.exit(1);
62+
});
63+
}
64+
65+
module.exports = { aggressiveKillPort, cleanupAllPorts };
Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,7 @@
1-
const kill = require('kill-port');
1+
const { cleanupAllPorts } = require('./aggressive-port-cleanup.cjs');
22

3-
async function killAllPorts() {
4-
const reactConsumerPorts = [3001, 3002, 3003, 3004, 3005, 3006, 3007];
5-
const exposePorts = [4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007];
6-
const nextConsumerPorts = [8081, 8082, 8083, 8084];
7-
8-
const allPorts = [...reactConsumerPorts, ...exposePorts, ...nextConsumerPorts];
9-
10-
console.log('[kill-all-ports] Killing all ports...');
11-
12-
for (const port of allPorts) {
13-
try {
14-
await kill(port, 'tcp');
15-
console.log(`[kill-all-ports] Killed port ${port}`);
16-
} catch (e) {
17-
// Port might not be in use, ignore
18-
}
19-
}
20-
21-
console.log('[kill-all-ports] All ports killed.');
22-
}
23-
24-
killAllPorts().catch(err => {
3+
// Just delegate to the aggressive cleanup
4+
cleanupAllPorts().catch(err => {
255
console.error('[kill-all-ports] Error:', err);
266
process.exit(1);
277
});

federated-css/scripts/start-all.cjs

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const waitOn = require('wait-on');
33
const path = require('node:path');
44
const fs = require('node:fs');
55
const kill = require('kill-port');
6+
const { aggressiveKillPort } = require('./aggressive-port-cleanup.cjs');
67

78
const root = path.resolve(__dirname, '..');
89

@@ -46,13 +47,17 @@ async function main() {
4647

4748
const procs = [];
4849

49-
// Kill all potentially conflicting ports first
50-
console.log('[federated-css] cleaning up ports...');
50+
// Kill all potentially conflicting ports first using aggressive cleanup
51+
console.log('[federated-css] cleaning up ports aggressively...');
5152
const allPorts = [...reactConsumers.map(c => c.port), ...exposes, ...nextConsumers.map(c => c.port)];
52-
await Promise.all(allPorts.map(port => killPort(port)));
53+
54+
// Use aggressive cleanup for all ports
55+
for (const port of allPorts) {
56+
await aggressiveKillPort(port);
57+
}
5358

5459
// Give OS time to fully release ports
55-
await new Promise(resolve => setTimeout(resolve, 1000));
60+
await new Promise(resolve => setTimeout(resolve, 3000));
5661

5762
console.log('[federated-css] starting consumers-react (sequential servers)...');
5863
for (const { dir, port, serve } of reactConsumers) {
@@ -119,18 +124,11 @@ async function main() {
119124

120125
console.log('[federated-css] starting Next consumers (sequential dev servers)...');
121126
for (const { dir, port } of nextConsumers) {
122-
// Extra cleanup for each Next.js port in case previous one didn't clean up properly
123-
console.log(`[federated-css] cleaning up port ${port} before starting ${dir}...`);
124-
await killPort(port);
125-
// Try multiple times to ensure port is really free
126-
for (let i = 0; i < 3; i++) {
127-
try {
128-
await killPort(port);
129-
} catch (e) {
130-
// Ignore, port might already be free
131-
}
132-
await new Promise(resolve => setTimeout(resolve, 1000));
133-
}
127+
// Extra aggressive cleanup for each Next.js port
128+
console.log(`[federated-css] aggressively cleaning up port ${port} before starting ${dir}...`);
129+
await aggressiveKillPort(port);
130+
await new Promise(resolve => setTimeout(resolve, 2000));
131+
134132
const cwd = path.join('consumers-nextjs', dir);
135133
const p = run('pnpm', ['-C', cwd, 'run', 'start']);
136134
procs.push(p);

0 commit comments

Comments
 (0)