@servicetitan/startup 27.4.0 → 28.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands/get-command.d.ts.map +1 -1
- package/dist/cli/commands/get-command.js +4 -2
- package/dist/cli/commands/get-command.js.map +1 -1
- package/dist/cli/commands/init.d.ts +0 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +39 -9
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/mfe-package-clean.d.ts +14 -0
- package/dist/cli/commands/mfe-package-clean.d.ts.map +1 -0
- package/dist/cli/commands/mfe-package-clean.js +124 -0
- package/dist/cli/commands/mfe-package-clean.js.map +1 -0
- package/dist/cli/commands/mfe-package-publish.d.ts +20 -0
- package/dist/cli/commands/mfe-package-publish.d.ts.map +1 -0
- package/dist/cli/commands/mfe-package-publish.js +153 -0
- package/dist/cli/commands/mfe-package-publish.js.map +1 -0
- package/dist/cli/commands/mfe-publish.d.ts +6 -30
- package/dist/cli/commands/mfe-publish.d.ts.map +1 -1
- package/dist/cli/commands/mfe-publish.js +14 -226
- package/dist/cli/commands/mfe-publish.js.map +1 -1
- package/dist/cli/utils/assets-copy.d.ts.map +1 -1
- package/dist/cli/utils/assets-copy.js +3 -3
- package/dist/cli/utils/assets-copy.js.map +1 -1
- package/dist/cli/utils/cli-os.d.ts +9 -2
- package/dist/cli/utils/cli-os.d.ts.map +1 -1
- package/dist/cli/utils/cli-os.js +16 -8
- package/dist/cli/utils/cli-os.js.map +1 -1
- package/dist/cli/utils/styles-copy.d.ts.map +1 -1
- package/dist/cli/utils/styles-copy.js +3 -3
- package/dist/cli/utils/styles-copy.js.map +1 -1
- package/dist/utils/get-branch-configs.d.ts +3 -0
- package/dist/utils/get-branch-configs.d.ts.map +1 -0
- package/dist/utils/get-branch-configs.js +18 -0
- package/dist/utils/get-branch-configs.js.map +1 -0
- package/dist/utils/get-configuration.d.ts +13 -3
- package/dist/utils/get-configuration.d.ts.map +1 -1
- package/dist/utils/get-configuration.js +28 -5
- package/dist/utils/get-configuration.js.map +1 -1
- package/dist/utils/get-folders.js +2 -2
- package/dist/utils/get-folders.js.map +1 -1
- package/dist/utils/get-jest-config.d.ts.map +1 -1
- package/dist/utils/get-jest-config.js +2 -10
- package/dist/utils/get-jest-config.js.map +1 -1
- package/dist/webpack/configs/dev-server-config.d.ts.map +1 -1
- package/dist/webpack/configs/dev-server-config.js +1 -1
- package/dist/webpack/configs/dev-server-config.js.map +1 -1
- package/dist/webpack/configs/plugins/ignore-plugin/is-optional-anvil-peer-dependency.js +1 -1
- package/dist/webpack/configs/plugins/ignore-plugin/is-optional-anvil-peer-dependency.js.map +1 -1
- package/dist/webpack/configs/plugins/index.d.ts +1 -0
- package/dist/webpack/configs/plugins/index.d.ts.map +1 -1
- package/dist/webpack/configs/plugins/index.js +1 -0
- package/dist/webpack/configs/plugins/index.js.map +1 -1
- package/dist/webpack/configs/plugins/virtual-modules-plugin.d.ts.map +1 -1
- package/dist/webpack/configs/plugins/virtual-modules-plugin.js +15 -5
- package/dist/webpack/configs/plugins/virtual-modules-plugin.js.map +1 -1
- package/dist/webpack/configs/plugins/watch-run-plugin.d.ts +8 -0
- package/dist/webpack/configs/plugins/watch-run-plugin.d.ts.map +1 -0
- package/dist/webpack/configs/plugins/watch-run-plugin.js +26 -0
- package/dist/webpack/configs/plugins/watch-run-plugin.js.map +1 -0
- package/dist/webpack/configs/plugins-config.d.ts.map +1 -1
- package/dist/webpack/configs/plugins-config.js +1 -0
- package/dist/webpack/configs/plugins-config.js.map +1 -1
- package/dist/webpack/configs/types.d.ts +16 -0
- package/dist/webpack/configs/types.d.ts.map +1 -1
- package/dist/webpack/configs/utils/generate-metadata.d.ts.map +1 -1
- package/dist/webpack/configs/utils/generate-metadata.js +3 -3
- package/dist/webpack/configs/utils/generate-metadata.js.map +1 -1
- package/jest/jest-preset.js +9 -0
- package/package.json +18 -23
- package/src/cli/commands/__tests__/init.test.ts +108 -28
- package/src/cli/commands/__tests__/mfe-package-clean.test.ts +45 -6
- package/src/cli/commands/__tests__/mfe-package-publish.test.ts +77 -7
- package/src/cli/commands/__tests__/mfe-publish.test.ts +19 -1
- package/src/cli/commands/__tests__/tests.test.ts +4 -0
- package/src/cli/commands/get-command.ts +3 -1
- package/src/cli/commands/init.ts +40 -10
- package/src/cli/commands/mfe-package-clean.ts +143 -0
- package/src/cli/commands/mfe-package-publish.ts +189 -0
- package/src/cli/commands/mfe-publish.ts +18 -298
- package/src/cli/utils/__tests__/assets-copy.test.ts +3 -7
- package/src/cli/utils/__tests__/cli-os.test.ts +41 -6
- package/src/cli/utils/__tests__/eslint.test.ts +4 -0
- package/src/cli/utils/__tests__/styles-copy.test.ts +3 -7
- package/src/cli/utils/assets-copy.ts +3 -3
- package/src/cli/utils/cli-os.ts +20 -8
- package/src/cli/utils/styles-copy.ts +3 -3
- package/src/utils/__tests__/get-branch-configs.test.ts +36 -0
- package/src/utils/__tests__/get-configuration.test.ts +65 -0
- package/src/utils/__tests__/get-jest-config.test.ts +1 -7
- package/src/utils/__tests__/load-shared-dependencies.test.ts +82 -88
- package/src/utils/get-branch-configs.ts +17 -0
- package/src/utils/get-configuration.ts +45 -7
- package/src/utils/get-folders.ts +1 -1
- package/src/utils/get-jest-config.ts +2 -10
- package/src/webpack/__tests__/create-webpack-config-shared-dependencies.test.ts +0 -1
- package/src/webpack/__tests__/create-webpack-config-web-component.test.ts +47 -13
- package/src/webpack/__tests__/create-webpack-config.test.ts +3 -2
- package/src/webpack/configs/dev-server-config.ts +2 -1
- package/src/webpack/configs/plugins/ignore-plugin/is-optional-anvil-peer-dependency.ts +1 -1
- package/src/webpack/configs/plugins/index.ts +1 -0
- package/src/webpack/configs/plugins/virtual-modules-plugin.ts +17 -5
- package/src/webpack/configs/plugins/watch-run-plugin.ts +23 -0
- package/src/webpack/configs/plugins-config.ts +2 -0
- package/src/webpack/configs/types.ts +19 -0
- package/src/webpack/configs/utils/generate-metadata.ts +5 -5
- package/tsconfig/base.json +1 -1
- package/template/.eslintrc.json +0 -3
- package/template/.gitignore +0 -21
- package/template/.npmrc +0 -3
- package/template/.prettierrc +0 -9
- package/template/.stylelintignore +0 -1
- package/template/.stylelintrc.json +0 -3
- package/template/.vscode/extensions.json +0 -18
- package/template/.vscode/settings.json +0 -4
- package/template/lerna.json +0 -4
- package/template/package.json +0 -32
- package/template/packages/application/package.json +0 -35
- package/template/packages/application/src/__tests__/app.test.tsx +0 -33
- package/template/packages/application/src/app.css +0 -3
- package/template/packages/application/src/app.tsx +0 -45
- package/template/packages/application/src/design-system.css +0 -3
- package/template/packages/application/src/index.tsx +0 -8
- package/template/packages/application/src/main-page.tsx +0 -5
- package/template/packages/application/src/second-page.tsx +0 -5
- package/template/packages/application/tsconfig.json +0 -13
- package/template/packages/feature-a/package.json +0 -19
- package/template/packages/feature-a/src/index.ts +0 -0
- package/template/packages/feature-a/tsconfig.json +0 -9
- package/template/packages/feature-b/package.json +0 -19
- package/template/packages/feature-b/src/index.ts +0 -0
- package/template/packages/feature-b/tsconfig.json +0 -9
- package/template/packages/feature-c/package.json +0 -19
- package/template/packages/feature-c/src/index.ts +0 -0
- package/template/packages/feature-c/tsconfig.json +0 -9
- package/template/setupTests.ts +0 -27
- package/template/tsconfig.test.json +0 -5
- package/template-react18/packages/application/package.json +0 -35
- package/template-react18/packages/application/src/index.tsx +0 -9
- package/template-react18/packages/feature-a/package.json +0 -19
- package/template-react18/packages/feature-b/package.json +0 -19
- package/template-react18/packages/feature-c/package.json +0 -19
- package/tsconfig.json +0 -13
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import { getFolders, isWebComponent, log, logErrors, readJson } from '../../utils';
|
|
4
|
+
import { gitGetBranch, gitGetCommitHash } from '../utils/cli-git';
|
|
5
|
+
import {
|
|
6
|
+
npmGetPackageVersions,
|
|
7
|
+
npmPackageSet,
|
|
8
|
+
npmPublish,
|
|
9
|
+
npmPublishDry,
|
|
10
|
+
npmTagVersion,
|
|
11
|
+
} from '../utils/cli-npm';
|
|
12
|
+
import { getBranchesConfigs } from '../../utils/get-branch-configs';
|
|
13
|
+
import { getDefaultBuildVersion } from '../utils/publish';
|
|
14
|
+
import { EntryPoint, EntryPoints, Metadata } from '../../webpack/configs';
|
|
15
|
+
import { Command } from './types';
|
|
16
|
+
|
|
17
|
+
export interface ArgsPackagePublish {
|
|
18
|
+
branch?: string;
|
|
19
|
+
build?: string;
|
|
20
|
+
dry?: boolean;
|
|
21
|
+
force?: boolean;
|
|
22
|
+
registry?: string;
|
|
23
|
+
tag?: string | false;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export class MFEPackagePublish implements Command {
|
|
27
|
+
constructor(private args: ArgsPackagePublish) {}
|
|
28
|
+
|
|
29
|
+
description() {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@logErrors
|
|
34
|
+
async execute() {
|
|
35
|
+
if (!isWebComponent()) {
|
|
36
|
+
throw new Error('only web-components can be published');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const packageJson = readJson('package.json');
|
|
40
|
+
|
|
41
|
+
if (packageJson.private) {
|
|
42
|
+
log.info('package is private, skipping publish');
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const data = this.getPublishData();
|
|
47
|
+
const packageName = packageJson.name;
|
|
48
|
+
|
|
49
|
+
if (!data.version) {
|
|
50
|
+
log.info('no build version found, skipping publish');
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!data.isBranchConfigured && !data.force) {
|
|
55
|
+
log.info(
|
|
56
|
+
'branch is not configured for publishing, use --force flag to publish if needed'
|
|
57
|
+
);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
this.validateMetadata();
|
|
62
|
+
|
|
63
|
+
const versions = npmGetPackageVersions(data.registry, packageName);
|
|
64
|
+
const dryRunPrefix = data.dry ? '(dry-run) ' : '';
|
|
65
|
+
|
|
66
|
+
if (versions.includes(data.version)) {
|
|
67
|
+
log.info(
|
|
68
|
+
`${dryRunPrefix}${packageName} version ${data.version} is already published, skipping publish`
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
if (data.tag) {
|
|
72
|
+
log.info(
|
|
73
|
+
`${dryRunPrefix}adding tag "${data.tag}" to ${packageName} version ${data.version}`
|
|
74
|
+
);
|
|
75
|
+
if (!data.dry) {
|
|
76
|
+
await npmTagVersion({
|
|
77
|
+
packageName,
|
|
78
|
+
packageVersion: data.version,
|
|
79
|
+
registry: data.registry,
|
|
80
|
+
tag: data.tag,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
await npmPackageSet('version', data.version);
|
|
88
|
+
await npmPackageSet('publishConfig.registry', data.registry);
|
|
89
|
+
|
|
90
|
+
if (!packageJson.files) {
|
|
91
|
+
await npmPackageSet('files[0]', 'dist');
|
|
92
|
+
await npmPackageSet('files[1]', 'package.json');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (data.dry) {
|
|
96
|
+
await npmPublishDry();
|
|
97
|
+
} else {
|
|
98
|
+
await npmPublish(data.tag);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
log.info(`${dryRunPrefix}published ${packageName} version ${data.version}`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private getPublishData(): {
|
|
105
|
+
version: string;
|
|
106
|
+
buildVersion: string;
|
|
107
|
+
tag?: string;
|
|
108
|
+
registry: string;
|
|
109
|
+
dry: boolean;
|
|
110
|
+
force: boolean;
|
|
111
|
+
isBranchConfigured: boolean;
|
|
112
|
+
} {
|
|
113
|
+
const cli = this.args;
|
|
114
|
+
const branch = cli.branch ?? gitGetBranch();
|
|
115
|
+
const branchConfig = getBranchesConfigs()[branch];
|
|
116
|
+
let buildVersion = cli.build;
|
|
117
|
+
|
|
118
|
+
if (!buildVersion) {
|
|
119
|
+
buildVersion = getDefaultBuildVersion(branch, gitGetCommitHash());
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (!buildVersion) {
|
|
123
|
+
throw new Error('build version is not set');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
let tag: string;
|
|
127
|
+
|
|
128
|
+
if (cli.tag === false) {
|
|
129
|
+
tag = '';
|
|
130
|
+
} else if (cli.tag) {
|
|
131
|
+
tag = cli.tag;
|
|
132
|
+
} else {
|
|
133
|
+
tag = branchConfig?.publishTag ?? '';
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const registry = cli.registry ?? 'https://verdaccio.servicetitan.com';
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
tag,
|
|
140
|
+
version: '0.0.0-' + buildVersion,
|
|
141
|
+
buildVersion,
|
|
142
|
+
registry,
|
|
143
|
+
dry: !!cli.dry,
|
|
144
|
+
force: !!cli.force,
|
|
145
|
+
isBranchConfigured: !!branchConfig,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
private validateMetadata() {
|
|
150
|
+
const { destination: outDir } = getFolders();
|
|
151
|
+
|
|
152
|
+
const metadataJson = path.join(outDir, 'metadata.json');
|
|
153
|
+
if (!fs.existsSync(metadataJson)) {
|
|
154
|
+
throw new Error(`${metadataJson} is not present`);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const metadata = readJson<Metadata>(metadataJson);
|
|
158
|
+
this.validateEntryPoints(outDir, metadata);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
private validateEntryPoints(outDir: string, { entrypoints = {} }: Metadata) {
|
|
162
|
+
const keys: (keyof EntryPoints)[] = ['full', 'light'];
|
|
163
|
+
keys.forEach(name =>
|
|
164
|
+
this.validateEntryPoint({ entryPoint: entrypoints[name], name, outDir })
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private validateEntryPoint({
|
|
169
|
+
entryPoint = {},
|
|
170
|
+
name,
|
|
171
|
+
outDir,
|
|
172
|
+
}: {
|
|
173
|
+
entryPoint?: EntryPoint;
|
|
174
|
+
name: keyof EntryPoints;
|
|
175
|
+
outDir: string;
|
|
176
|
+
}) {
|
|
177
|
+
const keys: (keyof EntryPoint)[] = ['css', 'js'];
|
|
178
|
+
keys.forEach(key => {
|
|
179
|
+
if (!entryPoint[key]) {
|
|
180
|
+
throw new Error(`${name}.${key} not found in metadata.json`);
|
|
181
|
+
}
|
|
182
|
+
entryPoint[key].forEach(filename => {
|
|
183
|
+
if (!fs.existsSync(path.join(outDir, 'bundle', name, filename))) {
|
|
184
|
+
throw new Error(`referenced bundle ${filename} was not found`);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
@@ -1,45 +1,18 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
|
|
3
1
|
import {
|
|
4
2
|
getPackages,
|
|
3
|
+
isWebComponent,
|
|
5
4
|
logErrors,
|
|
6
5
|
PackageType,
|
|
7
|
-
readJson,
|
|
8
6
|
splitPackagesByType,
|
|
9
|
-
isWebComponent,
|
|
10
|
-
log,
|
|
11
7
|
} from '../../utils';
|
|
8
|
+
import { ArgsPackageClean } from './mfe-package-clean';
|
|
9
|
+
import { ArgsPackagePublish } from './mfe-package-publish';
|
|
10
|
+
import { Command } from './types';
|
|
12
11
|
import { lernaExec } from '../utils';
|
|
13
|
-
import { gitGetBranch, gitGetCommitHash } from '../utils/cli-git';
|
|
14
|
-
import {
|
|
15
|
-
npmGetPackageVersionDates,
|
|
16
|
-
npmGetPackageVersions,
|
|
17
|
-
npmPackageSet,
|
|
18
|
-
npmPublish,
|
|
19
|
-
npmPublishDry,
|
|
20
|
-
npmTagVersion,
|
|
21
|
-
npmUnpublish,
|
|
22
|
-
} from '../utils/cli-npm';
|
|
23
|
-
import { getDefaultBuildVersion } from '../utils/publish';
|
|
24
|
-
import { Command } from '.';
|
|
25
|
-
|
|
26
|
-
interface ArgsPackagePublish {
|
|
27
|
-
branch?: string;
|
|
28
|
-
build?: string;
|
|
29
|
-
concurrency?: number;
|
|
30
|
-
dry?: boolean;
|
|
31
|
-
force?: boolean;
|
|
32
|
-
noTag?: string;
|
|
33
|
-
registry?: string;
|
|
34
|
-
tag?: string | false;
|
|
35
|
-
}
|
|
36
12
|
|
|
37
|
-
interface ArgsPackageClean {
|
|
38
|
-
count?: number;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
interface Args extends ArgsPackagePublish, ArgsPackageClean {
|
|
13
|
+
interface Args extends Omit<ArgsPackagePublish, 'branch'>, ArgsPackageClean {
|
|
42
14
|
clean?: boolean;
|
|
15
|
+
concurrency?: number;
|
|
43
16
|
scope?: string | string[];
|
|
44
17
|
}
|
|
45
18
|
|
|
@@ -53,11 +26,7 @@ export class MFEPublish implements Command {
|
|
|
53
26
|
@logErrors
|
|
54
27
|
async execute() {
|
|
55
28
|
let packages = splitPackagesByType(getPackages())[PackageType.Webpack] ?? [];
|
|
56
|
-
packages = packages.filter(p =>
|
|
57
|
-
const packageJson = readJson(path.join(p.location, 'package.json'));
|
|
58
|
-
|
|
59
|
-
return packageJson?.cli?.['web-component'] === true;
|
|
60
|
-
});
|
|
29
|
+
packages = packages.filter(p => isWebComponent(p.location));
|
|
61
30
|
|
|
62
31
|
if (this.args.scope) {
|
|
63
32
|
packages = packages.filter(p =>
|
|
@@ -71,21 +40,21 @@ export class MFEPublish implements Command {
|
|
|
71
40
|
throw new Error('no packages found for publication');
|
|
72
41
|
}
|
|
73
42
|
|
|
43
|
+
const isClean = !!this.args.clean;
|
|
74
44
|
await lernaExec({
|
|
75
|
-
'cmd': `startup mfe-package-${
|
|
45
|
+
'cmd': `startup mfe-package-${isClean ? 'clean' : 'publish'}`,
|
|
76
46
|
'concurrency': this.args.concurrency ?? 1,
|
|
77
47
|
'scope': packages.map(({ name }) => name),
|
|
78
48
|
'stream': true,
|
|
79
|
-
'--': this.getPublishOptions(),
|
|
49
|
+
'--': isClean ? this.getCleanOptions() : this.getPublishOptions(),
|
|
80
50
|
});
|
|
81
51
|
}
|
|
82
52
|
|
|
83
53
|
getPublishOptions() {
|
|
84
|
-
const { build, branch,
|
|
54
|
+
const { build, branch, dry, force, registry, tag } = this.args as ArgsPackagePublish;
|
|
85
55
|
return [
|
|
86
56
|
...[branch && `--branch ${branch}`],
|
|
87
57
|
...[build && `--build ${build}`],
|
|
88
|
-
...[count && `--count ${count}`],
|
|
89
58
|
...[dry && '--dry'],
|
|
90
59
|
...[force && '--force'],
|
|
91
60
|
...[registry && `--registry ${registry}`],
|
|
@@ -93,262 +62,13 @@ export class MFEPublish implements Command {
|
|
|
93
62
|
...[tag === false && `--no-tag`],
|
|
94
63
|
].filter(item => !!item) as string[];
|
|
95
64
|
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export class MFEPackagePublish implements Command {
|
|
99
|
-
constructor(private args: ArgsPackagePublish) {}
|
|
100
|
-
|
|
101
|
-
description() {
|
|
102
|
-
return undefined;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
@logErrors
|
|
106
|
-
async execute() {
|
|
107
|
-
if (!isWebComponent()) {
|
|
108
|
-
throw new Error('only web-components can be published');
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const packageJson = readJson('package.json');
|
|
112
|
-
|
|
113
|
-
if (packageJson.private) {
|
|
114
|
-
log.info('package is private, skipping publish');
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const data = this.getPublishData();
|
|
119
|
-
const packageName = packageJson.name;
|
|
120
|
-
|
|
121
|
-
if (!data.version) {
|
|
122
|
-
log.info('no build version found, skipping publish');
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (!data.isBranchConfigured && !data.force) {
|
|
127
|
-
log.info(
|
|
128
|
-
'branch is not configured for publishing, use --force flag to publish if needed'
|
|
129
|
-
);
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const versions = npmGetPackageVersions(data.registry, packageName);
|
|
134
|
-
const dryRunPrefix = data.dry ? '(dry-run) ' : '';
|
|
135
|
-
|
|
136
|
-
if (versions.includes(data.version)) {
|
|
137
|
-
log.info(
|
|
138
|
-
`${dryRunPrefix}${packageName} version ${data.version} is already published, skipping publish`
|
|
139
|
-
);
|
|
140
|
-
|
|
141
|
-
if (data.tag) {
|
|
142
|
-
log.info(
|
|
143
|
-
`${dryRunPrefix}adding tag "${data.tag}" to ${packageName} version ${data.version}`
|
|
144
|
-
);
|
|
145
|
-
if (!data.dry) {
|
|
146
|
-
await npmTagVersion({
|
|
147
|
-
packageName,
|
|
148
|
-
packageVersion: data.version,
|
|
149
|
-
registry: data.registry,
|
|
150
|
-
tag: data.tag,
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
await npmPackageSet('version', data.version);
|
|
158
|
-
await npmPackageSet('publishConfig.registry', data.registry);
|
|
159
|
-
|
|
160
|
-
if (!packageJson.files) {
|
|
161
|
-
await npmPackageSet('files[0]', 'dist');
|
|
162
|
-
await npmPackageSet('files[1]', 'package.json');
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
if (data.dry) {
|
|
166
|
-
await npmPublishDry();
|
|
167
|
-
} else {
|
|
168
|
-
await npmPublish(data.tag);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
log.info(`${dryRunPrefix}published ${packageName} version ${data.version}`);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
private getPublishData(): {
|
|
175
|
-
version: string;
|
|
176
|
-
buildVersion: string;
|
|
177
|
-
tag?: string;
|
|
178
|
-
registry: string;
|
|
179
|
-
dry: boolean;
|
|
180
|
-
force: boolean;
|
|
181
|
-
isBranchConfigured: boolean;
|
|
182
|
-
} {
|
|
183
|
-
const cli = this.args;
|
|
184
|
-
const branch = cli.branch ?? gitGetBranch();
|
|
185
|
-
const branchConfig = getBranchConfigs()[branch];
|
|
186
|
-
let buildVersion = cli.build;
|
|
187
65
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
let tag: string;
|
|
197
|
-
|
|
198
|
-
if (cli.tag === false) {
|
|
199
|
-
tag = '';
|
|
200
|
-
} else if (cli.tag) {
|
|
201
|
-
tag = cli.tag;
|
|
202
|
-
} else {
|
|
203
|
-
tag = branchConfig?.tag ?? '';
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
const registry = cli.registry ?? 'https://verdaccio.servicetitan.com';
|
|
207
|
-
|
|
208
|
-
return {
|
|
209
|
-
tag,
|
|
210
|
-
version: '0.0.0-' + buildVersion,
|
|
211
|
-
buildVersion,
|
|
212
|
-
registry,
|
|
213
|
-
dry: !!cli.dry,
|
|
214
|
-
force: !!cli.force,
|
|
215
|
-
isBranchConfigured: !!branchConfig,
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
export class MFEPackageClean implements Command {
|
|
221
|
-
constructor(private args: ArgsPackageClean) {}
|
|
222
|
-
|
|
223
|
-
description() {
|
|
224
|
-
return undefined;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
@logErrors
|
|
228
|
-
async execute() {
|
|
229
|
-
if (!isWebComponent()) {
|
|
230
|
-
throw new Error('only web-components can be cleaned');
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
const data = this.getCleanData();
|
|
234
|
-
const packageJson = readJson('package.json');
|
|
235
|
-
const packageName = packageJson.name;
|
|
236
|
-
const branchedVersions = this.getBranchedVersions(packageName, data.registry);
|
|
237
|
-
|
|
238
|
-
log.info(
|
|
239
|
-
`branched versions (${data.count}):`,
|
|
240
|
-
JSON.stringify(branchedVersions, undefined, 4)
|
|
241
|
-
);
|
|
242
|
-
|
|
243
|
-
const branchedVersionsToClean: Record<string, [string, Date][]> = {};
|
|
244
|
-
|
|
245
|
-
for (const branch of Object.keys(branchedVersions)) {
|
|
246
|
-
// limit branches for now
|
|
247
|
-
if (!branchedVersions[branch] || !data.branches.includes(branch)) {
|
|
248
|
-
continue;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
branchedVersions[branch].sort(([, adt], [, bdt]) => (adt > bdt ? -1 : 1));
|
|
252
|
-
branchedVersionsToClean[branch] = branchedVersions[branch].slice(data.count);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
log.info(
|
|
256
|
-
'found versions for unpublish:',
|
|
257
|
-
JSON.stringify(branchedVersionsToClean, undefined, 4)
|
|
258
|
-
);
|
|
259
|
-
|
|
260
|
-
const unVersions = Object.keys(branchedVersionsToClean).reduce(
|
|
261
|
-
(out, br) => [...out, ...branchedVersionsToClean[br].map(([v]) => v)],
|
|
262
|
-
[]
|
|
263
|
-
);
|
|
264
|
-
|
|
265
|
-
for (const version of unVersions) {
|
|
266
|
-
try {
|
|
267
|
-
// eslint-disable-next-line no-await-in-loop
|
|
268
|
-
await npmUnpublish(data.registry, packageName, version);
|
|
269
|
-
} catch {
|
|
270
|
-
log.error(`error while removing ${packageName} version ${version}`);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
private getCleanData(): {
|
|
276
|
-
count: number;
|
|
277
|
-
registry: string;
|
|
278
|
-
branches: string[];
|
|
279
|
-
} {
|
|
280
|
-
let count = this.args.count;
|
|
281
|
-
|
|
282
|
-
if (!count) {
|
|
283
|
-
count = 5;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
const registry = 'https://verdaccio.servicetitan.com';
|
|
287
|
-
|
|
288
|
-
return { count, registry, branches: Object.keys(getBranchConfigs()) };
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
private getBranchedVersions(packageName: string, registry: string) {
|
|
292
|
-
const versions = npmGetPackageVersionDates(registry, packageName);
|
|
293
|
-
const branchedVersions: Record<string, [string, Date][]> = {};
|
|
294
|
-
const unknownVersions: string[] = [];
|
|
295
|
-
|
|
296
|
-
const addVersion = (branch: string, version: string, dt: Date) => {
|
|
297
|
-
if (!branchedVersions[branch]) {
|
|
298
|
-
branchedVersions[branch] = [];
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
branchedVersions[branch].push([version, dt]);
|
|
302
|
-
};
|
|
303
|
-
|
|
304
|
-
for (const [version, dt] of versions) {
|
|
305
|
-
if (!version.startsWith('0.0.0-')) {
|
|
306
|
-
continue;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
const buildVersion = version.replace('0.0.0-', '');
|
|
310
|
-
|
|
311
|
-
if (/^(\d+)\.(\d+)\.(\d+)$/.test(buildVersion)) {
|
|
312
|
-
// master version generated by nerdbank versioning
|
|
313
|
-
addVersion('master', version, dt);
|
|
314
|
-
continue;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
const match1 = buildVersion.match(
|
|
318
|
-
/^(\d+)\.(\d+)\.(\d+)-([\dA-Za-z\-]+).([\dA-Za-z]+)$/
|
|
319
|
-
);
|
|
320
|
-
|
|
321
|
-
if (match1?.length) {
|
|
322
|
-
// branch version generated by nerdbank versioning
|
|
323
|
-
addVersion(match1[4], version, dt);
|
|
324
|
-
continue;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
const match2 = buildVersion.match(/^([\dA-Za-z\-]+).([\dA-Za-z]+)$/);
|
|
328
|
-
|
|
329
|
-
if (match2?.length) {
|
|
330
|
-
// branch version generated by mfe-publisher versioning
|
|
331
|
-
addVersion(match2[1], version, dt);
|
|
332
|
-
continue;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
unknownVersions.push(version);
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
if (unknownVersions.length) {
|
|
339
|
-
log.info('unknown versions:', unknownVersions.join());
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
return branchedVersions;
|
|
66
|
+
getCleanOptions() {
|
|
67
|
+
const { branch, count } = this.args as ArgsPackageClean;
|
|
68
|
+
return [
|
|
69
|
+
...[branch && typeof branch === 'string' && `--branch ${branch}`],
|
|
70
|
+
...[branch && branch === true && '--branch'],
|
|
71
|
+
...[count && `--count ${count}`],
|
|
72
|
+
].filter(item => !!item) as string[];
|
|
343
73
|
}
|
|
344
74
|
}
|
|
345
|
-
|
|
346
|
-
const getBranchConfigs = (): Record<string, { tag?: string }> => {
|
|
347
|
-
// ToDo: add ability to configure it in a package.json
|
|
348
|
-
return {
|
|
349
|
-
develop: { tag: 'dev' },
|
|
350
|
-
dev: { tag: 'dev' },
|
|
351
|
-
next: { tag: 'next' },
|
|
352
|
-
master: { tag: 'prod' },
|
|
353
|
-
};
|
|
354
|
-
};
|
|
@@ -5,10 +5,7 @@ import { assetsCopy, assetsCopyWatch } from '../assets-copy';
|
|
|
5
5
|
import { assetExtensions } from '../index';
|
|
6
6
|
|
|
7
7
|
jest.mock('cpx2', () => ({
|
|
8
|
-
|
|
9
|
-
const callback = args[args.length - 1];
|
|
10
|
-
callback(null);
|
|
11
|
-
}),
|
|
8
|
+
copySync: jest.fn(),
|
|
12
9
|
watch: jest.fn(() => ({ on: (_eventName: string, listener: Function) => listener() })),
|
|
13
10
|
}));
|
|
14
11
|
jest.mock('../../../utils', () => ({
|
|
@@ -28,10 +25,9 @@ describe('[startup] Cli Utils (Assets)', () => {
|
|
|
28
25
|
test('copies assets from source to destination', async () => {
|
|
29
26
|
await subject();
|
|
30
27
|
|
|
31
|
-
expect(cpx.
|
|
28
|
+
expect(cpx.copySync).toHaveBeenCalledWith(
|
|
32
29
|
`${source}/**/*.{${assetExtensions.join()}}`,
|
|
33
|
-
destination
|
|
34
|
-
expect.anything()
|
|
30
|
+
destination
|
|
35
31
|
);
|
|
36
32
|
});
|
|
37
33
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { execSync, spawn } from 'child_process';
|
|
2
2
|
|
|
3
3
|
import { runCommand, runCommandOutput } from '../cli-os';
|
|
4
|
+
import { log } from '../../../utils';
|
|
4
5
|
|
|
5
6
|
jest.mock('child_process', () => ({ execSync: jest.fn(), spawn: jest.fn() }));
|
|
6
7
|
jest.mock('../../../utils', () => ({ log: { info: jest.fn() } })); // suppress log output
|
|
@@ -11,6 +12,7 @@ describe('[startup] Cli Utils (OS)', () => {
|
|
|
11
12
|
let childProcess: ReturnType<typeof spawn>;
|
|
12
13
|
|
|
13
14
|
beforeEach(() => {
|
|
15
|
+
jest.clearAllMocks();
|
|
14
16
|
exitCode = 0;
|
|
15
17
|
childProcess = {
|
|
16
18
|
stderr: { pipe: jest.fn() },
|
|
@@ -25,7 +27,7 @@ describe('[startup] Cli Utils (OS)', () => {
|
|
|
25
27
|
test('runs command', () => {
|
|
26
28
|
expect(subject('foo bar')).resolves.toBe(undefined);
|
|
27
29
|
|
|
28
|
-
expect(spawn).toHaveBeenCalledWith('foo', ['bar'],
|
|
30
|
+
expect(spawn).toHaveBeenCalledWith('foo', ['bar'], {});
|
|
29
31
|
});
|
|
30
32
|
|
|
31
33
|
test('runs command with options', async () => {
|
|
@@ -37,7 +39,7 @@ describe('[startup] Cli Utils (OS)', () => {
|
|
|
37
39
|
test('runs command array', async () => {
|
|
38
40
|
await subject(['foo', 'bar', '--baz']);
|
|
39
41
|
|
|
40
|
-
expect(spawn).toHaveBeenCalledWith('foo', ['bar', '--baz'],
|
|
42
|
+
expect(spawn).toHaveBeenCalledWith('foo', ['bar', '--baz'], {});
|
|
41
43
|
});
|
|
42
44
|
|
|
43
45
|
test("pipes stdout and stderr to parent's streams", async () => {
|
|
@@ -60,10 +62,28 @@ describe('[startup] Cli Utils (OS)', () => {
|
|
|
60
62
|
expect(subject(command)).rejects.toBeUndefined();
|
|
61
63
|
})
|
|
62
64
|
);
|
|
65
|
+
|
|
66
|
+
test('logs command and exit status', async () => {
|
|
67
|
+
const logInfoSpy = jest.spyOn(log, 'info');
|
|
68
|
+
await subject('foo');
|
|
69
|
+
|
|
70
|
+
expect(logInfoSpy).toHaveBeenCalledWith('run command foo');
|
|
71
|
+
expect(logInfoSpy).toHaveBeenCalledWith('command finished with code 0', 'foo');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test('quiet option suppresses output', async () => {
|
|
75
|
+
const logInfoSpy = jest.spyOn(log, 'info');
|
|
76
|
+
await subject('foo', { quiet: true });
|
|
77
|
+
|
|
78
|
+
expect(logInfoSpy).not.toHaveBeenCalled();
|
|
79
|
+
});
|
|
63
80
|
});
|
|
64
81
|
|
|
65
82
|
describe(`${runCommandOutput.name}`, () => {
|
|
66
|
-
beforeEach(() =>
|
|
83
|
+
beforeEach(() => {
|
|
84
|
+
jest.clearAllMocks();
|
|
85
|
+
jest.mocked(execSync).mockReturnValue('');
|
|
86
|
+
});
|
|
67
87
|
|
|
68
88
|
const subject = (...args: Parameters<typeof runCommandOutput>) => runCommandOutput(...args);
|
|
69
89
|
|
|
@@ -73,7 +93,7 @@ describe('[startup] Cli Utils (OS)', () => {
|
|
|
73
93
|
|
|
74
94
|
expect(subject('foo bar')).toBe(result);
|
|
75
95
|
|
|
76
|
-
expect(execSync).toHaveBeenCalledWith('foo bar',
|
|
96
|
+
expect(execSync).toHaveBeenCalledWith('foo bar', {});
|
|
77
97
|
});
|
|
78
98
|
|
|
79
99
|
test('runs command with options', () => {
|
|
@@ -85,13 +105,13 @@ describe('[startup] Cli Utils (OS)', () => {
|
|
|
85
105
|
test('runs command array', () => {
|
|
86
106
|
subject(['foo', 'bar']);
|
|
87
107
|
|
|
88
|
-
expect(execSync).toHaveBeenCalledWith('foo bar',
|
|
108
|
+
expect(execSync).toHaveBeenCalledWith('foo bar', {});
|
|
89
109
|
});
|
|
90
110
|
|
|
91
111
|
test('ignores false and "" array values', () => {
|
|
92
112
|
subject(['', 'foo', false, '', 'bar', false]);
|
|
93
113
|
|
|
94
|
-
expect(execSync).toHaveBeenCalledWith('foo bar',
|
|
114
|
+
expect(execSync).toHaveBeenCalledWith('foo bar', {});
|
|
95
115
|
});
|
|
96
116
|
|
|
97
117
|
['', [], ['']].forEach(command =>
|
|
@@ -99,5 +119,20 @@ describe('[startup] Cli Utils (OS)', () => {
|
|
|
99
119
|
expect(() => subject(command)).toThrow();
|
|
100
120
|
})
|
|
101
121
|
);
|
|
122
|
+
|
|
123
|
+
test('logs command and result', () => {
|
|
124
|
+
const logInfoSpy = jest.spyOn(log, 'info');
|
|
125
|
+
subject('foo');
|
|
126
|
+
|
|
127
|
+
expect(logInfoSpy).toHaveBeenCalledWith('run command foo');
|
|
128
|
+
expect(logInfoSpy).toHaveBeenCalledWith('command finished', '');
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test('quiet option suppresses output', () => {
|
|
132
|
+
const logInfoSpy = jest.spyOn(log, 'info');
|
|
133
|
+
subject('foo', { quiet: true });
|
|
134
|
+
|
|
135
|
+
expect(logInfoSpy).not.toHaveBeenCalled();
|
|
136
|
+
});
|
|
102
137
|
});
|
|
103
138
|
});
|
|
@@ -63,8 +63,12 @@ describe(`[startup] utils:${eslint.name}`, () => {
|
|
|
63
63
|
});
|
|
64
64
|
|
|
65
65
|
describe('when there are errors', () => {
|
|
66
|
+
const exitCode = process.exitCode;
|
|
67
|
+
|
|
66
68
|
beforeEach(() => (eslintErrors = [mockResult]));
|
|
67
69
|
|
|
70
|
+
afterAll(() => (process.exitCode = exitCode));
|
|
71
|
+
|
|
68
72
|
test('sets process exitCode', async () => {
|
|
69
73
|
await subject();
|
|
70
74
|
|