Skip to content

Commit b7cbee2

Browse files
authored
Pick random server port on init (#333)
This gives the initialised template a stable port to `skuba start` on. With any luck the randomness will also reduce the chance of collisions in the event that you need to run multiple projects locally at once.
1 parent e7254c1 commit b7cbee2

File tree

11 files changed

+58
-10
lines changed

11 files changed

+58
-10
lines changed

.changeset/fifty-ladybugs-fly.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'skuba': patch
3+
---
4+
5+
**init:** Pick random server port

src/cli/init/getConfig.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import fs from 'fs-extra';
77
import { copyFiles } from '../../utils/copy';
88
import { isErrorWithCode } from '../../utils/error';
99
import { log } from '../../utils/logging';
10+
import { getRandomPort } from '../../utils/port';
1011
import {
1112
TEMPLATE_CONFIG_FILENAME,
1213
TEMPLATE_DIR,
@@ -143,12 +144,15 @@ export const getTemplateConfig = (dir: string): TemplateConfig => {
143144
}
144145
};
145146

146-
const baseToTemplateData = ({ ownerName, repoName }: BaseFields) => {
147+
const baseToTemplateData = async ({ ownerName, repoName }: BaseFields) => {
147148
const [orgName, teamName] = ownerName.split('/');
148149

150+
const port = String(await getRandomPort());
151+
149152
return {
150153
orgName,
151154
ownerName,
155+
port,
152156
repoName,
153157
// Use standalone username in `teamName` contexts
154158
teamName: teamName ?? orgName,
@@ -159,7 +163,7 @@ export const configureFromPrompt = async (): Promise<InitConfig> => {
159163
const { ownerName, repoName } = await runForm(BASE_PROMPT_PROPS);
160164
log.plain(chalk.cyan(repoName), 'by', chalk.cyan(ownerName));
161165

162-
const templateData = baseToTemplateData({ ownerName, repoName });
166+
const templateData = await baseToTemplateData({ ownerName, repoName });
163167

164168
const destinationDir = repoName;
165169

@@ -258,7 +262,7 @@ const configureFromPipe = async (): Promise<InitConfig> => {
258262
const { destinationDir, templateComplete, templateName } = result.value;
259263

260264
const templateData = {
261-
...baseToTemplateData(result.value.templateData),
265+
...(await baseToTemplateData(result.value.templateData)),
262266
...result.value.templateData,
263267
};
264268

src/cli/init/types.ts

+3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ const InitConfig = t.Record({
3333
// Derived from ownerName
3434
orgName: t.String,
3535
teamName: t.String,
36+
37+
// Generated by init command
38+
port: t.String,
3639
})
3740
.And(t.Dictionary(t.String, 'string')),
3841

src/utils/port.test.ts

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { randomIntBetween } from './port';
2+
3+
describe('randomIntBetween', () => {
4+
it('generates integers between min and max inclusive', () => {
5+
const min = 1000;
6+
const max = 2000;
7+
8+
for (let i = 0; i < 1000; i++) {
9+
const output = randomIntBetween(min, max);
10+
11+
expect(output).toBeGreaterThanOrEqual(min);
12+
expect(output).toBeLessThanOrEqual(max);
13+
expect(Number.isSafeInteger(output)).toBe(true);
14+
}
15+
});
16+
});

src/utils/port.ts

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import getPort from 'get-port';
2+
3+
/* Smallest 5-digit port; these are less common than 4-digit ports. */
4+
const MIN_PORT = 10000;
5+
6+
/** Largest port in the IANA user port range. */
7+
const MAX_PORT = 49151;
8+
9+
export const randomIntBetween = (min: number, max: number) =>
10+
min + Math.floor(Math.random() * (1 + max - min));
11+
12+
export const getRandomPort = () => {
13+
// Seed some random ports to use, if available.
14+
// get-port falls back to the private port range.
15+
const preferredPorts = new Array(10)
16+
.fill(null)
17+
.map(() => randomIntBetween(MIN_PORT, MAX_PORT));
18+
19+
return getPort({ port: preferredPorts });
20+
};

template/express-rest-api/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"format": "skuba format",
2323
"lint": "skuba lint",
2424
"start": "ENVIRONMENT=local skuba start",
25-
"start:debug": "ENVIRONMENT=local skuba start --inspect-brk",
25+
"start:debug": "yarn start --inspect-brk",
2626
"test": "skuba test --coverage",
2727
"test:watch": "skuba test --watch"
2828
}

template/express-rest-api/src/config.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const configs: Record<Environment, () => Omit<Config, 'environment'>> = {
2929
region: 'ap-southeast-2',
3030
version: 'local',
3131

32-
port: Env.nonNegativeInteger('PORT', { default: undefined }),
32+
port: Env.nonNegativeInteger('PORT', { default: Number('<%- port %>') }),
3333
}),
3434

3535
test: () => ({

template/greeter/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"format": "skuba format",
1717
"lint": "skuba lint",
1818
"start": "ENVIRONMENT=local skuba start",
19-
"start:debug": "ENVIRONMENT=local skuba start --inspect-brk",
19+
"start:debug": "yarn start --inspect-brk",
2020
"test": "skuba test --coverage",
2121
"test:watch": "skuba test --watch"
2222
}

template/koa-rest-api/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"format": "skuba format",
3737
"lint": "skuba lint",
3838
"start": "ENVIRONMENT=local skuba start",
39-
"start:debug": "ENVIRONMENT=local skuba start --inspect-brk",
39+
"start:debug": "yarn start --inspect-brk",
4040
"test": "skuba test --coverage",
4141
"test:watch": "skuba test --watch"
4242
}

template/koa-rest-api/src/config.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const configs: Record<Environment, () => Omit<Config, 'environment'>> = {
2929
region: 'ap-southeast-2',
3030
version: 'local',
3131

32-
port: Env.nonNegativeInteger('PORT', { default: undefined }),
32+
port: Env.nonNegativeInteger('PORT', { default: Number('<%- port %>') }),
3333
}),
3434

3535
test: () => ({

template/lambda-sqs-worker/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
"format": "skuba format",
3030
"lint": "skuba lint",
3131
"smoke": "serverless invoke --data '{}' --function Worker",
32-
"start": "ENVIRONMENT=local skuba start",
33-
"start:debug": "ENVIRONMENT=local skuba start --inspect-brk",
32+
"start": "ENVIRONMENT=local skuba start --port <%- port %>",
33+
"start:debug": "yarn start --inspect-brk",
3434
"test": "skuba test --coverage",
3535
"test:watch": "skuba test --watch"
3636
}

0 commit comments

Comments
 (0)