@teambit/snapping 1.0.108 → 1.0.109
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/artifacts/__bit_junit.xml +9 -0
- package/artifacts/preview/teambit_component_snapping-preview.js +1 -0
- package/package.json +21 -21
- package/components-have-issues.ts +0 -39
- package/flattened-edges.ts +0 -189
- package/generate-comp-from-scope.ts +0 -124
- package/index.ts +0 -8
- package/reset-cmd.ts +0 -70
- package/snap-cmd.ts +0 -195
- package/snap-distance-cmd.ts +0 -29
- package/snap-from-scope.cmd.ts +0 -155
- package/snapping.aspect.ts +0 -5
- package/snapping.main.runtime.ts +0 -1331
- package/snapping.spec.ts +0 -52
- package/tag-cmd.ts +0 -360
- package/tag-from-scope.cmd.ts +0 -258
- package/tag-model-component.ts +0 -641
- /package/dist/{preview-1703647408454.js → preview-1703698405864.js} +0 -0
package/snapping.spec.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import fs from 'fs-extra';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { loadAspect } from '@teambit/harmony.testing.load-aspect';
|
|
4
|
-
import {
|
|
5
|
-
mockWorkspace,
|
|
6
|
-
destroyWorkspace,
|
|
7
|
-
WorkspaceData,
|
|
8
|
-
setWorkspaceConfig,
|
|
9
|
-
} from '@teambit/workspace.testing.mock-workspace';
|
|
10
|
-
import IssuesAspect from '@teambit/issues';
|
|
11
|
-
import { CompilerAspect, CompilerMain } from '@teambit/compiler';
|
|
12
|
-
import { mockComponents } from '@teambit/component.testing.mock-components';
|
|
13
|
-
import { SnappingMain } from './snapping.main.runtime';
|
|
14
|
-
import { SnappingAspect } from './snapping.aspect';
|
|
15
|
-
import { ComponentsHaveIssues } from './components-have-issues';
|
|
16
|
-
|
|
17
|
-
describe('Snapping aspect', () => {
|
|
18
|
-
let workspaceData: WorkspaceData;
|
|
19
|
-
let snapping: SnappingMain;
|
|
20
|
-
describe('components with issues', () => {
|
|
21
|
-
beforeAll(async () => {
|
|
22
|
-
workspaceData = mockWorkspace();
|
|
23
|
-
const { workspacePath } = workspaceData;
|
|
24
|
-
// eslint-disable-next-line no-console
|
|
25
|
-
console.log('workspace created at ', workspacePath);
|
|
26
|
-
await mockComponents(workspacePath);
|
|
27
|
-
await fs.writeFile(path.join(workspacePath, 'comp1/index.js'), `const nonExist = require("non-exist");`);
|
|
28
|
-
const compiler: CompilerMain = await loadAspect(CompilerAspect, workspacePath);
|
|
29
|
-
await compiler.compileOnWorkspace();
|
|
30
|
-
snapping = await loadAspect(SnappingAspect, workspacePath);
|
|
31
|
-
}, 30000);
|
|
32
|
-
it('tag should throw an ComponentsHaveIssues error', async () => {
|
|
33
|
-
try {
|
|
34
|
-
await snapping.tag({ ids: ['comp1'] });
|
|
35
|
-
} catch (err: any) {
|
|
36
|
-
expect(err.constructor.name).toEqual(ComponentsHaveIssues.name);
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
// @todo: this test fails during "bit build" for some reason. It passes on "bit test";
|
|
40
|
-
it.skip('should not throw an error if the config was set to ignore MissingPackagesDependenciesOnFs error', async () => {
|
|
41
|
-
await setWorkspaceConfig(workspaceData.workspacePath, IssuesAspect.id, {
|
|
42
|
-
ignoreIssues: ['MissingPackagesDependenciesOnFs'],
|
|
43
|
-
});
|
|
44
|
-
snapping = await loadAspect(SnappingAspect, workspaceData.workspacePath);
|
|
45
|
-
const results = await snapping.tag({ ids: ['comp1'] });
|
|
46
|
-
expect(results?.taggedComponents.length).toEqual(1);
|
|
47
|
-
});
|
|
48
|
-
afterAll(async () => {
|
|
49
|
-
await destroyWorkspace(workspaceData);
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
});
|
package/tag-cmd.ts
DELETED
|
@@ -1,360 +0,0 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
import { ComponentIdList, ComponentID } from '@teambit/component-id';
|
|
3
|
-
import { Command, CommandOptions } from '@teambit/cli';
|
|
4
|
-
import { NOTHING_TO_TAG_MSG, AUTO_TAGGED_MSG } from '@teambit/legacy/dist/api/consumer/lib/tag';
|
|
5
|
-
import ConsumerComponent from '@teambit/legacy/dist/consumer/component/consumer-component';
|
|
6
|
-
import {
|
|
7
|
-
DEFAULT_BIT_RELEASE_TYPE,
|
|
8
|
-
COMPONENT_PATTERN_HELP,
|
|
9
|
-
CFG_FORCE_LOCAL_BUILD,
|
|
10
|
-
} from '@teambit/legacy/dist/constants';
|
|
11
|
-
import { GlobalConfigMain } from '@teambit/global-config';
|
|
12
|
-
import { IssuesClasses } from '@teambit/component-issues';
|
|
13
|
-
import { ReleaseType } from 'semver';
|
|
14
|
-
import { BitError } from '@teambit/bit-error';
|
|
15
|
-
import { Logger } from '@teambit/logger';
|
|
16
|
-
import { TagResults, SnappingMain } from './snapping.main.runtime';
|
|
17
|
-
import { BasicTagParams } from './tag-model-component';
|
|
18
|
-
|
|
19
|
-
const RELEASE_TYPES = ['major', 'premajor', 'minor', 'preminor', 'patch', 'prepatch', 'prerelease'];
|
|
20
|
-
|
|
21
|
-
export class TagCmd implements Command {
|
|
22
|
-
name = 'tag [component-patterns...]';
|
|
23
|
-
group = 'development';
|
|
24
|
-
description = 'create an immutable and exportable component snapshot, tagged with a release version.';
|
|
25
|
-
extendedDescription = `if no patterns are provided, it will tag all new and modified components.
|
|
26
|
-
if patterns are entered, you can specify a version per pattern using "@" sign, e.g. bit tag foo@1.0.0 bar@minor baz@major`;
|
|
27
|
-
arguments = [
|
|
28
|
-
{
|
|
29
|
-
name: 'component-patterns...',
|
|
30
|
-
description: `${COMPONENT_PATTERN_HELP}. By default, all new and modified are tagged.`,
|
|
31
|
-
},
|
|
32
|
-
];
|
|
33
|
-
helpUrl = 'reference/components/snaps#create-a-tag-(release-version)';
|
|
34
|
-
alias = 't';
|
|
35
|
-
loader = true;
|
|
36
|
-
options = [
|
|
37
|
-
['m', 'message <message>', 'a log message describing latest changes'],
|
|
38
|
-
['u', 'unmodified', 'include unmodified components (by default, only new and modified components are tagged)'],
|
|
39
|
-
[
|
|
40
|
-
'',
|
|
41
|
-
'editor [editor]',
|
|
42
|
-
'open an editor to write a tag message for each component. optionally, specify the editor-name (defaults to vim).',
|
|
43
|
-
],
|
|
44
|
-
['v', 'ver <version>', 'tag with the given version'],
|
|
45
|
-
['l', 'increment <level>', `options are: [${RELEASE_TYPES.join(', ')}], default to patch`],
|
|
46
|
-
['', 'prerelease-id <id>', 'prerelease identifier (e.g. "dev" to get "1.0.0-dev.1")'],
|
|
47
|
-
['p', 'patch', 'syntactic sugar for "--increment patch"'],
|
|
48
|
-
['', 'minor', 'syntactic sugar for "--increment minor"'],
|
|
49
|
-
['', 'major', 'syntactic sugar for "--increment major"'],
|
|
50
|
-
['', 'pre-release [identifier]', 'syntactic sugar for "--increment prerelease" and `--prerelease-id <identifier>`'],
|
|
51
|
-
['', 'snapped', 'tag only components whose head is a snap (not a tag)'],
|
|
52
|
-
['', 'unmerged', 'complete a merge process by tagging the unmerged components'],
|
|
53
|
-
['', 'skip-tests', 'skip running component tests during tag process'],
|
|
54
|
-
['', 'skip-auto-tag', 'skip auto tagging dependents'],
|
|
55
|
-
['', 'soft', 'do not persist. only keep note of the changes to be made'],
|
|
56
|
-
[
|
|
57
|
-
'',
|
|
58
|
-
'persist [skip-build]',
|
|
59
|
-
'persist the changes generated by --soft tag. by default, run the build pipeline, unless "skip-build" is provided',
|
|
60
|
-
],
|
|
61
|
-
['', 'disable-tag-pipeline', 'skip the tag pipeline to avoid publishing the components'],
|
|
62
|
-
['', 'force-deploy', 'DEPRECATED. use --ignore-build-error instead'],
|
|
63
|
-
['', 'ignore-build-errors', 'proceed to tag pipeline even when build pipeline fails'],
|
|
64
|
-
['', 'rebuild-deps-graph', 'do not reuse the saved dependencies graph, instead build it from scratch'],
|
|
65
|
-
[
|
|
66
|
-
'',
|
|
67
|
-
'increment-by <number>',
|
|
68
|
-
'(default to 1) increment semver flag (patch/minor/major) by. e.g. incrementing patch by 2: 0.0.1 -> 0.0.3.',
|
|
69
|
-
],
|
|
70
|
-
[
|
|
71
|
-
'i',
|
|
72
|
-
'ignore-issues [issues]',
|
|
73
|
-
`ignore component issues (shown in "bit status" as "issues found"), issues to ignore:
|
|
74
|
-
[${Object.keys(IssuesClasses).join(', ')}]
|
|
75
|
-
to ignore multiple issues, separate them by a comma and wrap with quotes. to ignore all issues, specify "*".`,
|
|
76
|
-
],
|
|
77
|
-
[
|
|
78
|
-
'I',
|
|
79
|
-
'ignore-newest-version',
|
|
80
|
-
'allow tagging even when the component has newer versions e.g. for hotfixes (default = false)',
|
|
81
|
-
],
|
|
82
|
-
[
|
|
83
|
-
'',
|
|
84
|
-
'fail-fast',
|
|
85
|
-
'stop pipeline execution on the first failed task (by default a task is skipped only when its dependency failed)',
|
|
86
|
-
],
|
|
87
|
-
['b', 'build', 'locally run the build pipeline (i.e. not via rippleCI) and complete the tag'],
|
|
88
|
-
[
|
|
89
|
-
'a',
|
|
90
|
-
'all [version]',
|
|
91
|
-
'DEPRECATED (not needed anymore, it is the default now). tag all new and modified components',
|
|
92
|
-
],
|
|
93
|
-
['s', 'scope [version]', 'DEPRECATED (use "--unmodified" instead). tag all components of the local scope'],
|
|
94
|
-
[
|
|
95
|
-
'f',
|
|
96
|
-
'force',
|
|
97
|
-
'DEPRECATED (use "--skip-tests", "--ignore-build-errors" or "--unmodified" instead). force-tag even if tests are failing and even when component has not changed',
|
|
98
|
-
],
|
|
99
|
-
['', 'disable-deploy-pipeline', 'DEPRECATED. use --disable-tag-pipeline instead'],
|
|
100
|
-
] as CommandOptions;
|
|
101
|
-
migration = true;
|
|
102
|
-
remoteOp = true; // In case a compiler / tester is not installed
|
|
103
|
-
examples = [{ cmd: 'tag --ver 1.0.0', description: 'tag all components to version 1.0.0' }];
|
|
104
|
-
|
|
105
|
-
constructor(private snapping: SnappingMain, private logger: Logger, private globalConfig: GlobalConfigMain) {}
|
|
106
|
-
|
|
107
|
-
// eslint-disable-next-line complexity
|
|
108
|
-
async report(
|
|
109
|
-
[patterns = []]: [string[]],
|
|
110
|
-
{
|
|
111
|
-
message = '',
|
|
112
|
-
ver,
|
|
113
|
-
all = false,
|
|
114
|
-
editor = '',
|
|
115
|
-
snapped = false,
|
|
116
|
-
unmerged = false,
|
|
117
|
-
patch,
|
|
118
|
-
minor,
|
|
119
|
-
major,
|
|
120
|
-
preRelease,
|
|
121
|
-
increment,
|
|
122
|
-
prereleaseId,
|
|
123
|
-
force = false,
|
|
124
|
-
ignoreUnresolvedDependencies,
|
|
125
|
-
ignoreIssues,
|
|
126
|
-
ignoreNewestVersion = false,
|
|
127
|
-
skipTests = false,
|
|
128
|
-
skipAutoTag = false,
|
|
129
|
-
scope,
|
|
130
|
-
unmodified = false,
|
|
131
|
-
build,
|
|
132
|
-
soft = false,
|
|
133
|
-
persist = false,
|
|
134
|
-
disableDeployPipeline = false,
|
|
135
|
-
disableTagPipeline = false,
|
|
136
|
-
forceDeploy = false,
|
|
137
|
-
ignoreBuildErrors = false,
|
|
138
|
-
rebuildDepsGraph,
|
|
139
|
-
failFast = false,
|
|
140
|
-
incrementBy = 1,
|
|
141
|
-
}: {
|
|
142
|
-
all?: boolean | string;
|
|
143
|
-
snapped?: boolean;
|
|
144
|
-
unmerged?: boolean;
|
|
145
|
-
ver?: string;
|
|
146
|
-
force?: boolean;
|
|
147
|
-
patch?: boolean;
|
|
148
|
-
minor?: boolean;
|
|
149
|
-
major?: boolean;
|
|
150
|
-
increment?: ReleaseType;
|
|
151
|
-
preRelease?: string;
|
|
152
|
-
prereleaseId?: string;
|
|
153
|
-
ignoreUnresolvedDependencies?: boolean;
|
|
154
|
-
ignoreIssues?: string;
|
|
155
|
-
scope?: string | boolean;
|
|
156
|
-
incrementBy?: number;
|
|
157
|
-
disableDeployPipeline?: boolean;
|
|
158
|
-
failFast?: boolean;
|
|
159
|
-
disableTagPipeline?: boolean;
|
|
160
|
-
forceDeploy?: boolean;
|
|
161
|
-
} & Partial<BasicTagParams>
|
|
162
|
-
): Promise<string> {
|
|
163
|
-
if (typeof ignoreUnresolvedDependencies === 'boolean') {
|
|
164
|
-
throw new BitError(`--ignore-unresolved-dependencies has been removed, please use --ignore-issues instead`);
|
|
165
|
-
}
|
|
166
|
-
if (ignoreIssues && typeof ignoreIssues === 'boolean') {
|
|
167
|
-
throw new BitError(`--ignore-issues expects issues to be ignored, please run "bit tag -h" for the issues list`);
|
|
168
|
-
}
|
|
169
|
-
if (disableDeployPipeline) {
|
|
170
|
-
this.logger.consoleWarning(`--disable-deploy-pipeline is deprecated, please use --disable-tag-pipeline instead`);
|
|
171
|
-
}
|
|
172
|
-
if (!message && !persist && !editor) {
|
|
173
|
-
this.logger.consoleWarning(
|
|
174
|
-
`--message will be mandatory in the next few releases. make sure to add a message with your tag`
|
|
175
|
-
);
|
|
176
|
-
}
|
|
177
|
-
if (all) {
|
|
178
|
-
this.logger.consoleWarning(
|
|
179
|
-
`--all is deprecated, please omit it. "bit tag" will by default tag all new and modified components`
|
|
180
|
-
);
|
|
181
|
-
if (typeof all === 'string') {
|
|
182
|
-
ver = all;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
if (scope) {
|
|
186
|
-
this.logger.consoleWarning(`--scope is deprecated, use --unmodified instead`);
|
|
187
|
-
unmodified = true;
|
|
188
|
-
if (typeof scope === 'string') {
|
|
189
|
-
ver = scope;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
if (force) {
|
|
193
|
-
this.logger.consoleWarning(
|
|
194
|
-
`--force is deprecated, use either --skip-tests, --ignore-build-errors or --unmodified depending on the use case`
|
|
195
|
-
);
|
|
196
|
-
if (patterns.length) unmodified = true;
|
|
197
|
-
}
|
|
198
|
-
if (prereleaseId && (!increment || increment === 'major' || increment === 'minor' || increment === 'patch')) {
|
|
199
|
-
throw new BitError(
|
|
200
|
-
`--prerelease-id should be entered along with --increment flag, while --increment must be one of the following: [prepatch, prerelease, preminor, premajor]`
|
|
201
|
-
);
|
|
202
|
-
}
|
|
203
|
-
if (forceDeploy) {
|
|
204
|
-
this.logger.consoleWarning(`--force-deploy is deprecated, use --ignore-build-errors instead`);
|
|
205
|
-
ignoreBuildErrors = true;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
const releaseFlags = [patch, minor, major, preRelease].filter((x) => x);
|
|
209
|
-
if (releaseFlags.length > 1) {
|
|
210
|
-
throw new BitError('you can use only one of the following - patch, minor, major, pre-release');
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
const getReleaseType = (): ReleaseType => {
|
|
214
|
-
if (increment) {
|
|
215
|
-
if (!RELEASE_TYPES.includes(increment)) {
|
|
216
|
-
throw new BitError(`invalid increment-level "${increment}".
|
|
217
|
-
semver allows the following options only: ${RELEASE_TYPES.join(', ')}`);
|
|
218
|
-
}
|
|
219
|
-
return increment;
|
|
220
|
-
}
|
|
221
|
-
if (major) return 'major';
|
|
222
|
-
if (minor) return 'minor';
|
|
223
|
-
if (patch) return 'patch';
|
|
224
|
-
if (preRelease) return 'prerelease';
|
|
225
|
-
return DEFAULT_BIT_RELEASE_TYPE;
|
|
226
|
-
};
|
|
227
|
-
const getPreReleaseId = (): string | undefined => {
|
|
228
|
-
if (prereleaseId) {
|
|
229
|
-
return prereleaseId;
|
|
230
|
-
}
|
|
231
|
-
if (preRelease && typeof preRelease === 'string') {
|
|
232
|
-
return preRelease;
|
|
233
|
-
}
|
|
234
|
-
return undefined;
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
const disableTagAndSnapPipelines = disableTagPipeline || disableDeployPipeline;
|
|
238
|
-
build = (await this.globalConfig.getBool(CFG_FORCE_LOCAL_BUILD)) || Boolean(build);
|
|
239
|
-
if (persist) {
|
|
240
|
-
if (persist === true) build = true;
|
|
241
|
-
else if (persist === 'skip-build') build = false;
|
|
242
|
-
else throw new BitError(`unknown value for --persist, use either --persist or --persist=skip-build`);
|
|
243
|
-
}
|
|
244
|
-
if (!build && !soft) {
|
|
245
|
-
this.logger.consoleWarning(
|
|
246
|
-
`tagging components on "main" lane when using remote build is not recommended. To avoid SemVer versions of your component with failing builds, please refer to:
|
|
247
|
-
- Snap changes in a different lane and merge to "main" on your remote (learn more on lanes - https://bit.dev/reference/lanes/getting-started-with-lanes)
|
|
248
|
-
- Use \`bit tag --build\` to build your components locally.
|
|
249
|
-
- Use \`snap\` or \`build\` first to validate your build passing, and then version and export safely.
|
|
250
|
-
|
|
251
|
-
To undo local tag use the "bit reset" command.`
|
|
252
|
-
);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
const params = {
|
|
256
|
-
ids: patterns,
|
|
257
|
-
snapped,
|
|
258
|
-
unmerged,
|
|
259
|
-
editor,
|
|
260
|
-
message,
|
|
261
|
-
releaseType: getReleaseType(),
|
|
262
|
-
preReleaseId: getPreReleaseId(),
|
|
263
|
-
ignoreIssues,
|
|
264
|
-
ignoreNewestVersion,
|
|
265
|
-
skipTests,
|
|
266
|
-
skipAutoTag,
|
|
267
|
-
build,
|
|
268
|
-
soft,
|
|
269
|
-
persist,
|
|
270
|
-
unmodified,
|
|
271
|
-
disableTagAndSnapPipelines,
|
|
272
|
-
ignoreBuildErrors,
|
|
273
|
-
rebuildDepsGraph,
|
|
274
|
-
incrementBy,
|
|
275
|
-
version: ver,
|
|
276
|
-
failFast,
|
|
277
|
-
};
|
|
278
|
-
|
|
279
|
-
const results = await this.snapping.tag(params);
|
|
280
|
-
if (!results) return chalk.yellow(persist ? 'no soft-tag found' : NOTHING_TO_TAG_MSG);
|
|
281
|
-
const { taggedComponents, autoTaggedResults, warnings, newComponents, removedComponents }: TagResults = results;
|
|
282
|
-
const changedComponents = taggedComponents.filter((component) => !newComponents.searchWithoutVersion(component.id));
|
|
283
|
-
const addedComponents = taggedComponents.filter((component) => newComponents.searchWithoutVersion(component.id));
|
|
284
|
-
const autoTaggedCount = autoTaggedResults ? autoTaggedResults.length : 0;
|
|
285
|
-
|
|
286
|
-
const warningsOutput = warnings && warnings.length ? `${chalk.yellow(warnings.join('\n'))}\n\n` : '';
|
|
287
|
-
const tagExplanationPersist = `\n(use "bit export" to push these components to a remote")
|
|
288
|
-
(use "bit reset" to unstage versions)`;
|
|
289
|
-
const tagExplanationSoft = `\n(use "bit tag --persist" to persist the soft-tagged changes as a fully tagged version")
|
|
290
|
-
(use "bit reset --soft" to remove the soft-tags)`;
|
|
291
|
-
|
|
292
|
-
const tagExplanation = results.isSoftTag ? tagExplanationSoft : tagExplanationPersist;
|
|
293
|
-
|
|
294
|
-
const compInBold = (id: ComponentID) => {
|
|
295
|
-
const version = id.hasVersion() ? `@${id.version}` : '';
|
|
296
|
-
return `${chalk.bold(id.toStringWithoutVersion())}${version}`;
|
|
297
|
-
};
|
|
298
|
-
|
|
299
|
-
const outputComponents = (comps: ConsumerComponent[]) => {
|
|
300
|
-
return comps
|
|
301
|
-
.map((component) => {
|
|
302
|
-
let componentOutput = ` > ${compInBold(component.id)}`;
|
|
303
|
-
const autoTag = autoTaggedResults.filter((result) => result.triggeredBy.searchWithoutVersion(component.id));
|
|
304
|
-
if (autoTag.length) {
|
|
305
|
-
const autoTagComp = autoTag.map((a) => compInBold(a.component.id));
|
|
306
|
-
componentOutput += `\n ${AUTO_TAGGED_MSG}:
|
|
307
|
-
${autoTagComp.join('\n ')}`;
|
|
308
|
-
}
|
|
309
|
-
return componentOutput;
|
|
310
|
-
})
|
|
311
|
-
.join('\n');
|
|
312
|
-
};
|
|
313
|
-
|
|
314
|
-
const publishOutput = () => {
|
|
315
|
-
const { publishedPackages } = results;
|
|
316
|
-
if (!publishedPackages || !publishedPackages.length) return '';
|
|
317
|
-
const successTitle = `\n\n${chalk.green(
|
|
318
|
-
`published the following ${publishedPackages.length} component(s) successfully\n`
|
|
319
|
-
)}`;
|
|
320
|
-
const successCompsStr = publishedPackages.join('\n');
|
|
321
|
-
const successOutput = successCompsStr ? successTitle + successCompsStr : '';
|
|
322
|
-
return successOutput;
|
|
323
|
-
};
|
|
324
|
-
|
|
325
|
-
const softTagPrefix = results.isSoftTag ? 'soft-tagged ' : '';
|
|
326
|
-
const outputIfExists = (label, explanation, components: ConsumerComponent[]) => {
|
|
327
|
-
if (!components.length) return '';
|
|
328
|
-
return `\n${chalk.underline(softTagPrefix + label)}\n(${explanation})\n${outputComponents(components)}\n`;
|
|
329
|
-
};
|
|
330
|
-
|
|
331
|
-
const newDesc = results.isSoftTag
|
|
332
|
-
? 'set to be tagged with first version for components when persisted'
|
|
333
|
-
: 'first version for components';
|
|
334
|
-
const changedDesc = results.isSoftTag
|
|
335
|
-
? 'components that are set to get a version bump when persisted'
|
|
336
|
-
: 'components that got a version bump';
|
|
337
|
-
const softTagClarification = results.isSoftTag
|
|
338
|
-
? chalk.bold(
|
|
339
|
-
'\nkeep in mind that this is a soft-tag (changes recorded to be tagged), to persist the changes use --persist flag'
|
|
340
|
-
)
|
|
341
|
-
: '';
|
|
342
|
-
return (
|
|
343
|
-
outputIfExists('new components', newDesc, addedComponents) +
|
|
344
|
-
outputIfExists('changed components', changedDesc, changedComponents) +
|
|
345
|
-
outputIdsIfExists('removed components', removedComponents) +
|
|
346
|
-
publishOutput() +
|
|
347
|
-
warningsOutput +
|
|
348
|
-
chalk.green(
|
|
349
|
-
`\n${taggedComponents.length + autoTaggedCount} component(s) ${results.isSoftTag ? 'soft-' : ''}tagged`
|
|
350
|
-
) +
|
|
351
|
-
tagExplanation +
|
|
352
|
-
softTagClarification
|
|
353
|
-
);
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
export function outputIdsIfExists(label: string, ids?: ComponentIdList) {
|
|
358
|
-
if (!ids?.length) return '';
|
|
359
|
-
return `\n${chalk.underline(label)}\n${ids.map((id) => id.toStringWithoutVersion()).join('\n')}\n`;
|
|
360
|
-
}
|
package/tag-from-scope.cmd.ts
DELETED
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
import { Command, CommandOptions } from '@teambit/cli';
|
|
3
|
-
import { NOTHING_TO_TAG_MSG, AUTO_TAGGED_MSG } from '@teambit/legacy/dist/api/consumer/lib/tag';
|
|
4
|
-
import { DEFAULT_BIT_RELEASE_TYPE } from '@teambit/legacy/dist/constants';
|
|
5
|
-
import { getHarmonyVersion } from '@teambit/legacy/dist/bootstrap';
|
|
6
|
-
import { IssuesClasses } from '@teambit/component-issues';
|
|
7
|
-
import { ReleaseType } from 'semver';
|
|
8
|
-
import { BitError } from '@teambit/bit-error';
|
|
9
|
-
import { Logger } from '@teambit/logger';
|
|
10
|
-
import { SnappingMain, TagResults } from './snapping.main.runtime';
|
|
11
|
-
import { BasicTagParams } from './tag-model-component';
|
|
12
|
-
|
|
13
|
-
const RELEASE_TYPES = ['major', 'premajor', 'minor', 'preminor', 'patch', 'prepatch', 'prerelease'];
|
|
14
|
-
|
|
15
|
-
export type TagDataPerCompRaw = {
|
|
16
|
-
componentId: string;
|
|
17
|
-
dependencies?: string[];
|
|
18
|
-
versionToTag?: string;
|
|
19
|
-
prereleaseId?: string;
|
|
20
|
-
message?: string;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export class TagFromScopeCmd implements Command {
|
|
24
|
-
name = '_tag <data>';
|
|
25
|
-
group = 'development';
|
|
26
|
-
private = true;
|
|
27
|
-
description =
|
|
28
|
-
'tag components from a bare-scope by using build artifacts from previous snap and running the deploy-pipeline only';
|
|
29
|
-
extendedDescription = `this command should be running from a new bare scope, it first imports the components it needs and then processes the tag.
|
|
30
|
-
the input data is a stringified JSON of an array of the following object.
|
|
31
|
-
{
|
|
32
|
-
componentId: string; // ids always have scope, so it's safe to parse them from string
|
|
33
|
-
dependencies?: string[]; // e.g. [teambit/compiler@1.0.0, teambit/tester^@1.0.0, teambit/linter~@0.0.1]
|
|
34
|
-
versionToTag?: string; // specific version (e.g. '1.0.0') or semver (e.g. 'minor', 'patch')
|
|
35
|
-
prereleaseId?: string; // applicable when versionToTag is a pre-release. (e.g. "dev", for 1.0.0-dev.1)
|
|
36
|
-
message?: string; // tag-message.
|
|
37
|
-
}
|
|
38
|
-
an example of the final data: '[{"componentId":"ci.remote2/comp-b","dependencies":["ci.remote/comp1@0.0.2"]}]'
|
|
39
|
-
`;
|
|
40
|
-
alias = '';
|
|
41
|
-
loader = true;
|
|
42
|
-
options = [
|
|
43
|
-
['', 'push', 'export the updated objects to the original scopes once done'],
|
|
44
|
-
['m', 'message <message>', 'a log message describing latest changes'],
|
|
45
|
-
['v', 'ver <version>', 'tag with the given version'],
|
|
46
|
-
['l', 'increment <level>', `options are: [${RELEASE_TYPES.join(', ')}], default to patch`],
|
|
47
|
-
['', 'prerelease-id <id>', 'prerelease identifier (e.g. "dev" to get "1.0.0-dev.1")'],
|
|
48
|
-
['p', 'patch', 'syntactic sugar for "--increment patch"'],
|
|
49
|
-
['', 'minor', 'syntactic sugar for "--increment minor"'],
|
|
50
|
-
['', 'major', 'syntactic sugar for "--increment major"'],
|
|
51
|
-
['', 'pre-release [identifier]', 'syntactic sugar for "--increment prerelease" and `--prerelease-id <identifier>`'],
|
|
52
|
-
['', 'skip-tests', 'skip running component tests during tag process'],
|
|
53
|
-
['', 'disable-tag-pipeline', 'skip the tag pipeline to avoid publishing the components'],
|
|
54
|
-
['', 'force-deploy', 'DEPRECATED. use --ignore-build-error instead'],
|
|
55
|
-
['', 'ignore-build-errors', 'run the tag pipeline although the build pipeline failed'],
|
|
56
|
-
['', 'rebuild-deps-graph', 'do not reuse the saved dependencies graph, instead build it from scratch'],
|
|
57
|
-
[
|
|
58
|
-
'',
|
|
59
|
-
'increment-by <number>',
|
|
60
|
-
'(default to 1) increment semver flag (patch/minor/major) by. e.g. incrementing patch by 2: 0.0.1 -> 0.0.3.',
|
|
61
|
-
],
|
|
62
|
-
[
|
|
63
|
-
'i',
|
|
64
|
-
'ignore-issues [issues]',
|
|
65
|
-
`ignore component issues (shown in "bit status" as "issues found"), issues to ignore:
|
|
66
|
-
[${Object.keys(IssuesClasses).join(', ')}]
|
|
67
|
-
to ignore multiple issues, separate them by a comma and wrap with quotes. to ignore all issues, specify "*".`,
|
|
68
|
-
],
|
|
69
|
-
['I', 'ignore-newest-version', 'ignore existing of newer versions (default = false)'],
|
|
70
|
-
] as CommandOptions;
|
|
71
|
-
remoteOp = true; // In case a compiler / tester is not installed
|
|
72
|
-
|
|
73
|
-
constructor(private snapping: SnappingMain, private logger: Logger) {}
|
|
74
|
-
|
|
75
|
-
// eslint-disable-next-line complexity
|
|
76
|
-
async report(
|
|
77
|
-
[data]: [string],
|
|
78
|
-
{
|
|
79
|
-
push,
|
|
80
|
-
message = '',
|
|
81
|
-
ver,
|
|
82
|
-
patch,
|
|
83
|
-
minor,
|
|
84
|
-
major,
|
|
85
|
-
preRelease,
|
|
86
|
-
increment,
|
|
87
|
-
prereleaseId,
|
|
88
|
-
ignoreIssues,
|
|
89
|
-
ignoreNewestVersion = false,
|
|
90
|
-
skipTests = false,
|
|
91
|
-
disableTagPipeline = false,
|
|
92
|
-
forceDeploy = false,
|
|
93
|
-
ignoreBuildErrors = false,
|
|
94
|
-
rebuildDepsGraph,
|
|
95
|
-
incrementBy = 1,
|
|
96
|
-
}: {
|
|
97
|
-
push?: boolean;
|
|
98
|
-
ver?: string;
|
|
99
|
-
patch?: boolean;
|
|
100
|
-
minor?: boolean;
|
|
101
|
-
major?: boolean;
|
|
102
|
-
increment?: ReleaseType;
|
|
103
|
-
preRelease?: string;
|
|
104
|
-
prereleaseId?: string;
|
|
105
|
-
ignoreIssues?: string;
|
|
106
|
-
incrementBy?: number;
|
|
107
|
-
forceDeploy?: boolean;
|
|
108
|
-
disableTagPipeline?: boolean;
|
|
109
|
-
} & Partial<BasicTagParams>
|
|
110
|
-
): Promise<string> {
|
|
111
|
-
if (ignoreIssues && typeof ignoreIssues === 'boolean') {
|
|
112
|
-
throw new BitError(`--ignore-issues expects issues to be ignored, please run "bit tag -h" for the issues list`);
|
|
113
|
-
}
|
|
114
|
-
if (prereleaseId && (!increment || increment === 'major' || increment === 'minor' || increment === 'patch')) {
|
|
115
|
-
throw new BitError(
|
|
116
|
-
`--prerelease-id should be entered along with --increment flag, while --increment must be one of the following: [prepatch, prerelease, preminor, premajor]`
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const releaseFlags = [patch, minor, major, preRelease].filter((x) => x);
|
|
121
|
-
if (releaseFlags.length > 1) {
|
|
122
|
-
throw new BitError('you can use only one of the following - patch, minor, major, pre-release');
|
|
123
|
-
}
|
|
124
|
-
if (forceDeploy) {
|
|
125
|
-
this.logger.consoleWarning(`--force-deploy is deprecated, use --ignore-build-errors instead`);
|
|
126
|
-
ignoreBuildErrors = true;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
const getReleaseType = (): ReleaseType => {
|
|
130
|
-
if (increment) {
|
|
131
|
-
if (!RELEASE_TYPES.includes(increment)) {
|
|
132
|
-
throw new BitError(`invalid increment-level "${increment}".
|
|
133
|
-
semver allows the following options only: ${RELEASE_TYPES.join(', ')}`);
|
|
134
|
-
}
|
|
135
|
-
return increment;
|
|
136
|
-
}
|
|
137
|
-
if (major) return 'major';
|
|
138
|
-
if (minor) return 'minor';
|
|
139
|
-
if (patch) return 'patch';
|
|
140
|
-
if (preRelease) return 'prerelease';
|
|
141
|
-
return DEFAULT_BIT_RELEASE_TYPE;
|
|
142
|
-
};
|
|
143
|
-
const getPreReleaseId = (): string | undefined => {
|
|
144
|
-
if (prereleaseId) {
|
|
145
|
-
return prereleaseId;
|
|
146
|
-
}
|
|
147
|
-
if (preRelease && typeof preRelease === 'string') {
|
|
148
|
-
return preRelease;
|
|
149
|
-
}
|
|
150
|
-
return undefined;
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
const params = {
|
|
154
|
-
push,
|
|
155
|
-
message,
|
|
156
|
-
releaseType: getReleaseType(),
|
|
157
|
-
preReleaseId: getPreReleaseId(),
|
|
158
|
-
ignoreIssues,
|
|
159
|
-
ignoreNewestVersion,
|
|
160
|
-
skipTests,
|
|
161
|
-
build: true,
|
|
162
|
-
persist: true,
|
|
163
|
-
disableTagAndSnapPipelines: disableTagPipeline,
|
|
164
|
-
ignoreBuildErrors,
|
|
165
|
-
rebuildDepsGraph,
|
|
166
|
-
forceDeploy,
|
|
167
|
-
incrementBy,
|
|
168
|
-
version: ver,
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
const tagDataPerCompRaw = this.parseData(data);
|
|
172
|
-
this.logger.console(`tagging using ${getHarmonyVersion()} version`);
|
|
173
|
-
const results = await this.snapping.tagFromScope(tagDataPerCompRaw, params);
|
|
174
|
-
if (!results) return chalk.yellow(NOTHING_TO_TAG_MSG);
|
|
175
|
-
const { taggedComponents, autoTaggedResults, warnings, newComponents }: TagResults = results;
|
|
176
|
-
const changedComponents = taggedComponents.filter((component) => !newComponents.searchWithoutVersion(component.id));
|
|
177
|
-
const addedComponents = taggedComponents.filter((component) => newComponents.searchWithoutVersion(component.id));
|
|
178
|
-
const autoTaggedCount = autoTaggedResults ? autoTaggedResults.length : 0;
|
|
179
|
-
|
|
180
|
-
const warningsOutput = warnings && warnings.length ? `${chalk.yellow(warnings.join('\n'))}\n\n` : '';
|
|
181
|
-
const tagExplanationPersist = `\n(use "bit export [collection]" to push these components to a remote")
|
|
182
|
-
(use "bit reset" to unstage versions)\n`;
|
|
183
|
-
const tagExplanationSoft = `\n(use "bit tag --persist" to persist the changes")
|
|
184
|
-
(use "bit reset --soft" to remove the soft-tags)\n`;
|
|
185
|
-
|
|
186
|
-
const tagExplanation = results.isSoftTag ? tagExplanationSoft : tagExplanationPersist;
|
|
187
|
-
|
|
188
|
-
const outputComponents = (comps) => {
|
|
189
|
-
return comps
|
|
190
|
-
.map((component) => {
|
|
191
|
-
let componentOutput = ` > ${component.id.toString()}`;
|
|
192
|
-
const autoTag = autoTaggedResults.filter((result) => result.triggeredBy.searchWithoutVersion(component.id));
|
|
193
|
-
if (autoTag.length) {
|
|
194
|
-
const autoTagComp = autoTag.map((a) => a.component.id.toString());
|
|
195
|
-
componentOutput += `\n ${AUTO_TAGGED_MSG}:
|
|
196
|
-
${autoTagComp.join('\n ')}`;
|
|
197
|
-
}
|
|
198
|
-
return componentOutput;
|
|
199
|
-
})
|
|
200
|
-
.join('\n');
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
const publishOutput = () => {
|
|
204
|
-
const { publishedPackages } = results;
|
|
205
|
-
if (!publishedPackages || !publishedPackages.length) return '';
|
|
206
|
-
const successTitle = `\n\n${chalk.green(
|
|
207
|
-
`published the following ${publishedPackages.length} component(s) successfully\n`
|
|
208
|
-
)}`;
|
|
209
|
-
const successCompsStr = publishedPackages.join('\n');
|
|
210
|
-
const successOutput = successCompsStr ? successTitle + successCompsStr : '';
|
|
211
|
-
return successOutput;
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
const softTagPrefix = results.isSoftTag ? 'soft-tagged ' : '';
|
|
215
|
-
const outputIfExists = (label, explanation, components) => {
|
|
216
|
-
if (!components.length) return '';
|
|
217
|
-
return `\n${chalk.underline(softTagPrefix + label)}\n(${explanation})\n${outputComponents(components)}\n`;
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
const newDesc = results.isSoftTag
|
|
221
|
-
? 'set to be tagged first version for components'
|
|
222
|
-
: 'first version for components';
|
|
223
|
-
const changedDesc = results.isSoftTag
|
|
224
|
-
? 'components that set to get a version bump'
|
|
225
|
-
: 'components that got a version bump';
|
|
226
|
-
const softTagClarification = results.isSoftTag
|
|
227
|
-
? chalk.bold(
|
|
228
|
-
'keep in mind that this is a soft-tag (changes recorded to be tagged), to persist the changes use --persist flag'
|
|
229
|
-
)
|
|
230
|
-
: '';
|
|
231
|
-
return (
|
|
232
|
-
warningsOutput +
|
|
233
|
-
chalk.green(
|
|
234
|
-
`${taggedComponents.length + autoTaggedCount} component(s) ${results.isSoftTag ? 'soft-' : ''}tagged`
|
|
235
|
-
) +
|
|
236
|
-
tagExplanation +
|
|
237
|
-
outputIfExists('new components', newDesc, addedComponents) +
|
|
238
|
-
outputIfExists('changed components', changedDesc, changedComponents) +
|
|
239
|
-
publishOutput() +
|
|
240
|
-
softTagClarification
|
|
241
|
-
);
|
|
242
|
-
}
|
|
243
|
-
private parseData(data: string): TagDataPerCompRaw[] {
|
|
244
|
-
let dataParsed: unknown;
|
|
245
|
-
try {
|
|
246
|
-
dataParsed = JSON.parse(data);
|
|
247
|
-
} catch (err: any) {
|
|
248
|
-
throw new Error(`failed parsing the data entered as JSON. err ${err.message}`);
|
|
249
|
-
}
|
|
250
|
-
if (!Array.isArray(dataParsed)) {
|
|
251
|
-
throw new Error('expect data to be an array');
|
|
252
|
-
}
|
|
253
|
-
dataParsed.forEach((dataItem) => {
|
|
254
|
-
if (!dataItem.componentId) throw new Error('expect data item to have "componentId" prop');
|
|
255
|
-
});
|
|
256
|
-
return dataParsed;
|
|
257
|
-
}
|
|
258
|
-
}
|