forked from storybookjs/storybook
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrun-registry.ts
executable file
·170 lines (144 loc) · 5.05 KB
/
run-registry.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
import { exec } from 'child_process';
import { remove, pathExists, readJSON } from 'fs-extra';
import chalk from 'chalk';
import path from 'path';
import program from 'commander';
import { runServer, parseConfigFile } from 'verdaccio';
import pLimit from 'p-limit';
import type { Server } from 'http';
import { mkdir } from 'fs/promises';
import { PACKS_DIRECTORY } from './utils/constants';
import { maxConcurrentTasks } from './utils/concurrency';
import { getWorkspaces } from './utils/workspace';
program
.option('-O, --open', 'keep process open')
.option('-P, --publish', 'should publish packages');
program.parse(process.argv);
const logger = console;
const startVerdaccio = async () => {
let resolved = false;
return Promise.race([
new Promise((resolve) => {
const cache = path.join(__dirname, '..', '.verdaccio-cache');
const config = {
...parseConfigFile(path.join(__dirname, 'verdaccio.yaml')),
self_path: cache,
};
// @ts-expect-error (verdaccio's interface is wrong)
runServer(config).then((app: Server) => {
app.listen(6001, () => {
resolved = true;
resolve(app);
});
});
}),
new Promise((_, rej) => {
setTimeout(() => {
if (!resolved) {
resolved = true;
rej(new Error(`TIMEOUT - verdaccio didn't start within 10s`));
}
}, 10000);
}),
]) as Promise<Server>;
};
const currentVersion = async () => {
const { version } = await readJSON(path.join(__dirname, '..', 'code', 'package.json'));
return version;
};
const publish = async (packages: { name: string; location: string }[], url: string) => {
logger.log(`Publishing packages with a concurrency of ${maxConcurrentTasks}`);
const limit = pLimit(maxConcurrentTasks);
let i = 0;
/**
* We need to "pack" our packages before publishing to npm because our package.json files contain yarn specific version "ranges".
* such as "workspace:*"
*
* We can't publish to npm if the package.json contains these ranges. So with `yarn pack` we create a tarball that we can publish.
*
* However this bug exists in NPM: https://github.com/npm/cli/issues/4533!
* Which causes the NPM CLI to disregard the tarball CLI argument and instead re-create a tarball.
* But NPM doesn't replace the yarn version ranges.
*
* So we create the tarball ourselves and move it to another location on the FS.
* Then we change-directory to that directory and publish the tarball from there.
*/
await mkdir(PACKS_DIRECTORY, { recursive: true }).catch(() => {});
return Promise.all(
packages.map(({ name, location }) =>
limit(
() =>
new Promise((res, rej) => {
logger.log(
`🛫 publishing ${name} (${location.replace(
path.resolve(path.join(__dirname, '..')),
'.'
)})`
);
const tarballFilename = `${name.replace('@', '').replace('/', '-')}.tgz`;
const command = `cd ${path.resolve(
'../code',
location
)} && yarn pack --out=${PACKS_DIRECTORY}/${tarballFilename} && cd ${PACKS_DIRECTORY} && npm publish ./${tarballFilename} --registry ${url} --force --access restricted --ignore-scripts`;
exec(command, (e) => {
if (e) {
rej(e);
} else {
i += 1;
logger.log(`${i}/${packages.length} 🛬 successful publish of ${name}!`);
res(undefined);
}
});
})
)
)
);
};
const addUser = (url: string) =>
new Promise<void>((res, rej) => {
logger.log(`👤 add temp user to verdaccio`);
exec(`npx npm-cli-adduser -r "${url}" -a -u user -p password -e [email protected]`, (e) => {
if (e) {
rej(e);
} else {
res();
}
});
});
const run = async () => {
const verdaccioUrl = `http://localhost:6001`;
logger.log(`📐 reading version of storybook`);
logger.log(`🚛 listing storybook packages`);
if (!process.env.CI) {
// when running e2e locally, clear cache to avoid EPUBLISHCONFLICT errors
const verdaccioCache = path.resolve(__dirname, '..', '.verdaccio-cache');
if (await pathExists(verdaccioCache)) {
logger.log(`🗑 cleaning up cache`);
await remove(verdaccioCache);
}
}
logger.log(`🎬 starting verdaccio (this takes ±5 seconds, so be patient)`);
const [verdaccioServer, packages, version] = await Promise.all([
startVerdaccio(),
getWorkspaces(false),
currentVersion(),
]);
logger.log(`🌿 verdaccio running on ${verdaccioUrl}`);
// in some environments you need to add a dummy user. always try to add & catch on failure
try {
await addUser(verdaccioUrl);
} catch (e) {
//
}
logger.log(`📦 found ${packages.length} storybook packages at version ${chalk.blue(version)}`);
if (program.publish) {
await publish(packages, verdaccioUrl);
}
if (!program.open) {
verdaccioServer.close();
}
};
run().catch((e) => {
logger.error(e);
process.exit(1);
});