Skip to content

Commit fd87687

Browse files
fix: use kill-port npm package for reliable cross-platform port cleanup
- Replace manual port killing (lsof/fuser) with kill-port npm package - Add kill-port as workspace dependency - Update all startup scripts in federated-css and federated-css-react-ssr - Ensures consistent port cleanup across CI and local environments 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent a2c49a5 commit fd87687

File tree

6 files changed

+619
-754
lines changed

6 files changed

+619
-754
lines changed

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

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,19 @@
1-
const { spawn, execSync } = require('node:child_process');
1+
const { spawn } = require('node:child_process');
22
const path = require('node:path');
33
const waitOn = require('wait-on');
4+
const kill = require('kill-port');
45

56
const root = path.resolve(__dirname, '..');
67

78
function run(cmd, args, opts = {}) {
89
return spawn(cmd, args, { stdio: 'inherit', cwd: root, shell: true, ...opts });
910
}
1011

11-
function killPort(port) {
12+
async function killPort(port) {
1213
try {
13-
// Try fuser first (more reliable in CI)
14-
execSync(`fuser -k ${port}/tcp 2>/dev/null || true`, { stdio: 'ignore' });
14+
await kill(port, 'tcp');
1515
} catch (e) {
16-
// Fallback to lsof for macOS/local development
17-
try {
18-
const pids = execSync(`lsof -ti tcp:${port} 2>/dev/null || true`, { encoding: 'utf8' }).trim();
19-
if (pids) {
20-
execSync(`kill -9 ${pids} 2>/dev/null || true`, { stdio: 'ignore' });
21-
}
22-
} catch (e2) {
23-
// Ignore errors, port might not be in use
24-
}
16+
// Port might not be in use, ignore
2517
}
2618
}
2719

@@ -46,7 +38,7 @@ async function main() {
4638

4739
// Clean up all ports first
4840
console.log('[exposes] cleaning up ports...');
49-
exposes.forEach(({ port }) => killPort(port));
41+
await Promise.all(exposes.map(({ port }) => killPort(port)));
5042
await new Promise(resolve => setTimeout(resolve, 1000));
5143

5244
const procs = [];

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

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,19 @@
1-
const { spawn, execSync } = require('node:child_process');
1+
const { spawn } = require('node:child_process');
22
const path = require('node:path');
33
const waitOn = require('wait-on');
4+
const kill = require('kill-port');
45

56
const root = path.resolve(__dirname, '..');
67

78
function run(cmd, args, opts = {}) {
89
return spawn(cmd, args, { stdio: 'inherit', cwd: root, shell: true, ...opts });
910
}
1011

11-
function killPort(port) {
12+
async function killPort(port) {
1213
try {
13-
// Try fuser first (more reliable in CI)
14-
execSync(`fuser -k ${port}/tcp 2>/dev/null || true`, { stdio: 'ignore' });
14+
await kill(port, 'tcp');
1515
} catch (e) {
16-
// Fallback to lsof for macOS/local development
17-
try {
18-
const pids = execSync(`lsof -ti tcp:${port} 2>/dev/null || true`, { encoding: 'utf8' }).trim();
19-
if (pids) {
20-
execSync(`kill -9 ${pids} 2>/dev/null || true`, { stdio: 'ignore' });
21-
}
22-
} catch (e2) {
23-
// Ignore errors, port might not be in use
24-
}
16+
// Port might not be in use, ignore
2517
}
2618
}
2719

@@ -45,7 +37,7 @@ async function main() {
4537

4638
// Clean up all ports first
4739
console.log('[shells] cleaning up ports...');
48-
shells.forEach(({ port }) => killPort(port));
40+
await Promise.all(shells.map(({ port }) => killPort(port)));
4941
await new Promise(resolve => setTimeout(resolve, 1000));
5042

5143
const procs = [];

federated-css/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
},
2828
"devDependencies": {
2929
"@playwright/test": "^1.54.2",
30+
"kill-port": "2.0.1",
3031
"wait-on": "7.2.0"
3132
}
3233
}

federated-css/scripts/start-all.cjs

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
const { spawn, execSync } = require('node:child_process');
1+
const { spawn } = require('node:child_process');
22
const waitOn = require('wait-on');
33
const path = require('node:path');
44
const fs = require('node:fs');
5+
const kill = require('kill-port');
56

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

@@ -15,20 +16,11 @@ function run(cmd, args) {
1516
return spawn(cmd, args, { stdio: 'inherit', cwd: root, shell: true });
1617
}
1718

18-
function killPort(port) {
19+
async function killPort(port) {
1920
try {
20-
// Try fuser first (more reliable in CI)
21-
execSync(`fuser -k ${port}/tcp 2>/dev/null || true`, { stdio: 'ignore' });
21+
await kill(port, 'tcp');
2222
} catch (e) {
23-
// Fallback to lsof for macOS/local development
24-
try {
25-
const pids = execSync(`lsof -ti tcp:${port} 2>/dev/null || true`, { encoding: 'utf8' }).trim();
26-
if (pids) {
27-
execSync(`kill -9 ${pids} 2>/dev/null || true`, { stdio: 'ignore' });
28-
}
29-
} catch (e2) {
30-
// Ignore errors, port might not be in use
31-
}
23+
// Port might not be in use, ignore
3224
}
3325
}
3426

@@ -56,7 +48,8 @@ async function main() {
5648

5749
// Kill all potentially conflicting ports first
5850
console.log('[federated-css] cleaning up ports...');
59-
[...reactConsumers.map(c => c.port), ...exposes, ...nextConsumers.map(c => c.port)].forEach(killPort);
51+
const allPorts = [...reactConsumers.map(c => c.port), ...exposes, ...nextConsumers.map(c => c.port)];
52+
await Promise.all(allPorts.map(port => killPort(port)));
6053

6154
// Give OS time to fully release ports
6255
await new Promise(resolve => setTimeout(resolve, 1000));

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
"husky": "9.0.11",
4949
"jest": "29.7.0",
5050
"js-yaml": "4.1.0",
51+
"kill-port": "2.0.1",
5152
"lerna": "8.1.8",
5253
"lint-staged": "^15.2.10",
5354
"mocha": "10.6.0",

0 commit comments

Comments
 (0)