Skip to content

Commit

Permalink
Build: Always cleanup verdaccio ports before running registry
Browse files Browse the repository at this point in the history
  • Loading branch information
yannbf committed Dec 11, 2024
1 parent bb14633 commit 89e2abe
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 4 deletions.
20 changes: 16 additions & 4 deletions scripts/run-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { parseConfigFile, runServer } from 'verdaccio';

import { maxConcurrentTasks } from './utils/concurrency';
import { PACKS_DIRECTORY } from './utils/constants';
import { killPort } from './utils/kill-port';
import { getWorkspaces } from './utils/workspace';

program
Expand Down Expand Up @@ -154,8 +155,17 @@ const publish = async (packages: { name: string; location: string }[], url: stri
);
};

const VERDACCIO_SERVER_PORT = 6001;
const VERDACCIO_REGISTRY_PORT = 6002;

const cleanupVerdaccioProcesses = async () => {
await killPort([VERDACCIO_SERVER_PORT, VERDACCIO_REGISTRY_PORT]);
};

const run = async () => {
const verdaccioUrl = `http://localhost:6001`;
await cleanupVerdaccioProcesses();

const verdaccioUrl = `http://localhost:${VERDACCIO_SERVER_PORT}`;

logger.log(`📐 reading version of storybook`);
logger.log(`🚛 listing storybook packages`);
Expand Down Expand Up @@ -192,7 +202,7 @@ const run = async () => {
'-e',
'test@test.com',
'-r',
'http://localhost:6002',
`http://localhost:${VERDACCIO_REGISTRY_PORT}`,
],
{
cwd: root,
Expand All @@ -204,7 +214,7 @@ const run = async () => {
);

if (opts.publish) {
await publish(packages, 'http://localhost:6002');
await publish(packages, `http://localhost:${VERDACCIO_REGISTRY_PORT}`);
}

await rm(join(root, '.npmrc'), { force: true });
Expand All @@ -218,6 +228,8 @@ const run = async () => {
run().catch((e) => {
logger.error(e);
rm(join(root, '.npmrc'), { force: true }).then(() => {
process.exit(1);
cleanupVerdaccioProcesses().then(() => {
process.exit(1);
});
});
});
89 changes: 89 additions & 0 deletions scripts/utils/kill-port.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// eslint-disable-next-line depend/ban-dependencies
import { execa } from 'execa';

/**
* This code is derived from the library `kill-port` by Tiaan du Plessis. Original repository:
* https://github.com/tiaanduplessis/kill-port
*
* The MIT License (MIT)
*
* Copyright (c) Tiaan du Plessis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
const killProcessInPort = async (port: number, method: 'tcp' | 'udp' = 'tcp') => {
if (!port || isNaN(port)) {
throw new Error('Invalid argument provided for port');
}
let args: string[] = [];
let command: string;

if (process.platform === 'win32') {
try {
const { stdout } = await execa('netstat', ['-nao']);

if (!stdout) {
return;
}

const lines = stdout.split('\n');
const lineWithLocalPortRegEx = new RegExp(`^ *${method.toUpperCase()} *[^ ]*:${port}`, 'gm');
const linesWithLocalPort = lines.filter((line) => line.match(lineWithLocalPortRegEx));

const pids = linesWithLocalPort.reduce<string[]>((acc, line) => {
const match = line.match(/\d+/gm);
if (match && match[0] && !acc.includes(match[0])) {
acc.push(match[0]);
}
return acc;
}, []);

if (pids.length > 0) {
args = ['/F', ...pids.flatMap((pid) => ['/PID', pid])];
command = 'TaskKill';
}
} catch (error) {
throw new Error(`Failed to detect process on port ${port}: ${(error as Error).message}`);
}
} else {
const protocol = method === 'udp' ? 'udp' : 'tcp';
args = [
'-c',
`lsof -i ${protocol}:${port} | grep ${method === 'udp' ? 'UDP' : 'LISTEN'} | awk '{print $2}' | xargs kill -9`,
];
command = 'sh';
}

try {
if (command) {
await execa(command, args);
} else {
throw new Error('No command to kill process found');
}
} catch (error: any) {
if (!error.message.includes('No such process')) {
console.error(`Failed to kill process on port ${port}`);
throw error;
}
}
};

export const killPort = async (ports: number | number[], method: 'tcp' | 'udp' = 'tcp') => {
const allPorts = Array.isArray(ports) ? ports : [ports];

console.log(`🚮 cleaning up process in ports: ${allPorts.join(', ')}`);
await Promise.all(allPorts.map((port) => killProcessInPort(port, method)));
};

0 comments on commit 89e2abe

Please sign in to comment.