@teambit/builder 0.0.551 → 0.0.556
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/artifact/artifact-definition.d.ts +35 -0
- package/dist/artifact/artifact-factory.d.ts +3 -0
- package/dist/artifact/artifact-list.d.ts +9 -0
- package/dist/artifact/artifact.d.ts +52 -1
- package/dist/build-pipe.d.ts +33 -1
- package/dist/build-pipeline-order.d.ts +30 -0
- package/dist/build-pipeline-result-list.d.ts +3 -0
- package/dist/build-task.d.ts +57 -0
- package/dist/builder.main.runtime.d.ts +27 -0
- package/dist/builder.service.d.ts +39 -1
- package/dist/storage/storage-resolver.d.ts +6 -0
- package/dist/task-results-list.d.ts +11 -1
- package/dist/tasks-queue.d.ts +3 -0
- package/dist/types.d.ts +18 -0
- package/package.json +23 -17
- package/artifact/artifact-definition.ts +0 -52
- package/artifact/artifact-extractor.ts +0 -116
- package/artifact/artifact-factory.ts +0 -119
- package/artifact/artifact-list.ts +0 -64
- package/artifact/artifact.ts +0 -81
- package/artifact/artifacts.cmd.ts +0 -68
- package/artifact/extension-artifact.ts +0 -12
- package/artifact/index.ts +0 -5
- package/build-pipe.ts +0 -167
- package/build-pipeline-order.ts +0 -197
- package/build-pipeline-result-list.ts +0 -97
- package/build-task.ts +0 -114
- package/build.cmd.ts +0 -91
- package/builder.aspect.ts +0 -5
- package/builder.docs.mdx +0 -8
- package/builder.graphql.ts +0 -38
- package/builder.main.runtime.ts +0 -346
- package/builder.service.tsx +0 -163
- package/exceptions/artifact-storage-error.ts +0 -7
- package/exceptions/capsule-not-found.ts +0 -7
- package/exceptions/index.ts +0 -3
- package/exceptions/invalid-task.ts +0 -7
- package/index.ts +0 -9
- package/package-tar/teambit-builder-0.0.551.tgz +0 -0
- package/pipeline/index.ts +0 -1
- package/pipeline/pipeline-results.ts +0 -1
- package/storage/default-resolver.ts +0 -13
- package/storage/index.ts +0 -2
- package/storage/s3-resolver.ts +0 -40
- package/storage/storage-resolver.ts +0 -18
- package/task-results-list.ts +0 -66
- package/tasks-queue.ts +0 -40
- package/tsconfig.json +0 -35
- package/types/asset.d.ts +0 -29
- package/types/style.d.ts +0 -42
- package/types.ts +0 -39
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import fs from 'fs-extra';
|
|
3
|
-
import { ScopeMain } from '@teambit/scope';
|
|
4
|
-
import { ComponentID } from '@teambit/component-id';
|
|
5
|
-
import pMapSeries from 'p-map-series';
|
|
6
|
-
import minimatch from 'minimatch';
|
|
7
|
-
import { ArtifactFiles, ArtifactObject } from '@teambit/legacy/dist/consumer/component/sources/artifact-files';
|
|
8
|
-
import { BuilderMain } from '../builder.main.runtime';
|
|
9
|
-
import { ArtifactsOpts } from './artifacts.cmd';
|
|
10
|
-
|
|
11
|
-
export type ExtractorResult = {
|
|
12
|
-
id: ComponentID;
|
|
13
|
-
artifacts: ExtractorArtifactResult[];
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export type ExtractorArtifactResult = {
|
|
17
|
-
aspectId: string;
|
|
18
|
-
taskName: string;
|
|
19
|
-
files: string[];
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export type ExtractorResultGrouped = {
|
|
23
|
-
id: ComponentID;
|
|
24
|
-
artifacts: { [aspectId: string]: ExtractorArtifactResult[] };
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
type ArtifactObjectsPerId = {
|
|
28
|
-
id: ComponentID;
|
|
29
|
-
artifacts: ArtifactObject[];
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
export class ArtifactExtractor {
|
|
33
|
-
constructor(
|
|
34
|
-
private scope: ScopeMain,
|
|
35
|
-
private builder: BuilderMain,
|
|
36
|
-
private patterns: string[],
|
|
37
|
-
private options: ArtifactsOpts
|
|
38
|
-
) {}
|
|
39
|
-
|
|
40
|
-
async list(): Promise<ExtractorResult[]> {
|
|
41
|
-
const components = await this.scope.byPattern(this.patterns);
|
|
42
|
-
const artifactObjectsPerId: ArtifactObjectsPerId[] = components.map((component) => {
|
|
43
|
-
return {
|
|
44
|
-
id: component.id,
|
|
45
|
-
artifacts: this.builder.getArtifacts(component) || [],
|
|
46
|
-
};
|
|
47
|
-
});
|
|
48
|
-
this.filterByOptions(artifactObjectsPerId);
|
|
49
|
-
await this.saveFilesInFileSystemIfAsked(artifactObjectsPerId);
|
|
50
|
-
|
|
51
|
-
return this.artifactsObjectsToExtractorResults(artifactObjectsPerId);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
groupResultsByAspect(extractorResult: ExtractorResult[]) {
|
|
55
|
-
return extractorResult.map((result) => {
|
|
56
|
-
const artifacts = result.artifacts.reduce((acc, current) => {
|
|
57
|
-
(acc[current.aspectId] ||= []).push(current);
|
|
58
|
-
return acc;
|
|
59
|
-
}, {});
|
|
60
|
-
return { id: result.id, artifacts };
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
private async saveFilesInFileSystemIfAsked(artifactObjectsPerId: ArtifactObjectsPerId[]) {
|
|
65
|
-
const outDir = this.options.outDir;
|
|
66
|
-
if (!outDir) {
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
// @todo: optimize this to first import all missing hashes.
|
|
70
|
-
await pMapSeries(artifactObjectsPerId, async ({ id, artifacts }) => {
|
|
71
|
-
const vinyls = await Promise.all(
|
|
72
|
-
artifacts.map((artifactObject) =>
|
|
73
|
-
artifactObject.files.getVinylsAndImportIfMissing(id.scope as string, this.scope.legacyScope)
|
|
74
|
-
)
|
|
75
|
-
);
|
|
76
|
-
const flattenedVinyls = vinyls.flat();
|
|
77
|
-
const compPath = path.join(outDir, id.toStringWithoutVersion());
|
|
78
|
-
await Promise.all(flattenedVinyls.map((vinyl) => fs.outputFile(path.join(compPath, vinyl.path), vinyl.contents)));
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
private artifactsObjectsToExtractorResults(artifactObjectsPerId: ArtifactObjectsPerId[]): ExtractorResult[] {
|
|
83
|
-
return artifactObjectsPerId.map(({ id, artifacts }) => {
|
|
84
|
-
const results: ExtractorArtifactResult[] = artifacts.map((artifact) => {
|
|
85
|
-
return {
|
|
86
|
-
aspectId: artifact.task.id,
|
|
87
|
-
taskName: artifact.task.name || artifact.generatedBy,
|
|
88
|
-
files: artifact.files.refs.map((ref) => ref.relativePath),
|
|
89
|
-
};
|
|
90
|
-
});
|
|
91
|
-
return {
|
|
92
|
-
id,
|
|
93
|
-
artifacts: results,
|
|
94
|
-
};
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
private filterByOptions(artifactObjectsPerId: ArtifactObjectsPerId[]) {
|
|
99
|
-
const { aspect, task, files } = this.options;
|
|
100
|
-
artifactObjectsPerId.forEach((item) => {
|
|
101
|
-
item.artifacts = item.artifacts.filter((artifact) => {
|
|
102
|
-
if (aspect && aspect !== artifact.task.id) return false;
|
|
103
|
-
if (task && task !== artifact.task.name) return false;
|
|
104
|
-
return true;
|
|
105
|
-
});
|
|
106
|
-
if (files) {
|
|
107
|
-
item.artifacts.forEach((artifact) => {
|
|
108
|
-
const refs = artifact.files.refs.filter((ref) => minimatch(ref.relativePath, files));
|
|
109
|
-
artifact.files = new ArtifactFiles([], [], refs);
|
|
110
|
-
});
|
|
111
|
-
// remove artifacts with no files
|
|
112
|
-
item.artifacts = item.artifacts.filter((artifact) => artifact.files.refs.length);
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
}
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import { join } from 'path';
|
|
2
|
-
import globby from 'globby';
|
|
3
|
-
import { flatten } from 'lodash';
|
|
4
|
-
import { ArtifactFiles } from '@teambit/legacy/dist/consumer/component/sources/artifact-files';
|
|
5
|
-
import { Component, ComponentMap } from '@teambit/component';
|
|
6
|
-
import type { StorageResolverSlot } from '../builder.main.runtime';
|
|
7
|
-
import { ArtifactDefinition } from './artifact-definition';
|
|
8
|
-
import { DefaultResolver, StorageResolver } from '../storage';
|
|
9
|
-
import { ArtifactList } from './artifact-list';
|
|
10
|
-
import { Artifact } from './artifact';
|
|
11
|
-
import type { BuildContext, BuildTask } from '../build-task';
|
|
12
|
-
import { CapsuleNotFound } from '../exceptions';
|
|
13
|
-
|
|
14
|
-
export const DEFAULT_CONTEXT = 'component';
|
|
15
|
-
|
|
16
|
-
export type ArtifactMap = ComponentMap<ArtifactList>;
|
|
17
|
-
|
|
18
|
-
export class ArtifactFactory {
|
|
19
|
-
constructor(private storageResolverSlot: StorageResolverSlot) {}
|
|
20
|
-
|
|
21
|
-
private getResolver(resolvers: StorageResolver[], name?: string) {
|
|
22
|
-
const defaultResolver = new DefaultResolver();
|
|
23
|
-
const userResolver = resolvers.find((resolver) => resolver.name === name);
|
|
24
|
-
return userResolver || defaultResolver;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
private resolvePaths(root: string, def: ArtifactDefinition): string[] {
|
|
28
|
-
const patternsFlattened = flatten(def.globPatterns);
|
|
29
|
-
const paths = globby.sync(patternsFlattened, { cwd: root });
|
|
30
|
-
return paths;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
private getArtifactContextPath(context: BuildContext, component: Component, def: ArtifactDefinition) {
|
|
34
|
-
const artifactContext = this.getArtifactContext(def);
|
|
35
|
-
if (artifactContext === 'component') {
|
|
36
|
-
const capsulePath = context.capsuleNetwork.graphCapsules.getCapsule(component.id)?.path;
|
|
37
|
-
if (!capsulePath) throw new CapsuleNotFound(component.id);
|
|
38
|
-
return capsulePath;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return context.capsuleNetwork.capsulesRootDir;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
private getArtifactContext(def: ArtifactDefinition) {
|
|
45
|
-
return def.context || DEFAULT_CONTEXT;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
createFromComponent(
|
|
49
|
-
context: BuildContext,
|
|
50
|
-
component: Component,
|
|
51
|
-
def: ArtifactDefinition,
|
|
52
|
-
task: BuildTask
|
|
53
|
-
): Artifact | undefined {
|
|
54
|
-
const storageResolver = this.getStorageResolver(def);
|
|
55
|
-
const rootDir = this.getArtifactContextPath(context, component, def);
|
|
56
|
-
const paths = this.resolvePaths(this.getRootDir(rootDir, def), def);
|
|
57
|
-
if (!paths || !paths.length) {
|
|
58
|
-
return undefined;
|
|
59
|
-
}
|
|
60
|
-
return new Artifact(def, storageResolver, new ArtifactFiles(paths), rootDir, task);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
private getStorageResolver(def: ArtifactDefinition) {
|
|
64
|
-
const storageResolvers = this.storageResolverSlot.values();
|
|
65
|
-
return this.getResolver(storageResolvers, def.storageResolver);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
private toComponentMap(context: BuildContext, artifactMap: [string, Artifact][]) {
|
|
69
|
-
return ComponentMap.as<ArtifactList>(context.components, (component) => {
|
|
70
|
-
const id = component.id.toString();
|
|
71
|
-
const artifacts = artifactMap.filter(([targetId]) => targetId === id).map(([, artifact]) => artifact);
|
|
72
|
-
|
|
73
|
-
return new ArtifactList(artifacts);
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
private getRootDir(rootDir: string, def: ArtifactDefinition) {
|
|
78
|
-
if (!def.rootDir) return rootDir;
|
|
79
|
-
return join(rootDir, def.rootDir);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* generate artifacts from a build context according to the spec defined in the artifact definitions.
|
|
84
|
-
*/
|
|
85
|
-
generate(context: BuildContext, defs: ArtifactDefinition[], task: BuildTask): ComponentMap<ArtifactList> {
|
|
86
|
-
const tupleArr: [string, Artifact][] = [];
|
|
87
|
-
|
|
88
|
-
defs.forEach((def) => {
|
|
89
|
-
const artifactContext = this.getArtifactContext(def);
|
|
90
|
-
if (artifactContext === 'env') {
|
|
91
|
-
const capsuleDir = context.capsuleNetwork.capsulesRootDir;
|
|
92
|
-
const rootDir = this.getRootDir(capsuleDir, def);
|
|
93
|
-
const paths = this.resolvePaths(rootDir, def);
|
|
94
|
-
if (paths && paths.length) {
|
|
95
|
-
const artifact = new Artifact(
|
|
96
|
-
def,
|
|
97
|
-
this.getStorageResolver(def),
|
|
98
|
-
new ArtifactFiles(this.resolvePaths(rootDir, def)),
|
|
99
|
-
rootDir,
|
|
100
|
-
task
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
return context.components.forEach((component) => {
|
|
104
|
-
tupleArr.push([component.id.toString(), artifact]);
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
return context.components.forEach((component) => {
|
|
110
|
-
const artifact = this.createFromComponent(context, component, def, task);
|
|
111
|
-
if (artifact) {
|
|
112
|
-
tupleArr.push([component.id.toString(), artifact]);
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
return this.toComponentMap(context, tupleArr);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { Component } from '@teambit/component';
|
|
2
|
-
import type { ArtifactObject } from '@teambit/legacy/dist/consumer/component/sources/artifact-files';
|
|
3
|
-
import type { Artifact } from './artifact';
|
|
4
|
-
|
|
5
|
-
export type ResolverMap = { [key: string]: Artifact[] };
|
|
6
|
-
|
|
7
|
-
export class ArtifactList {
|
|
8
|
-
constructor(readonly artifacts: Artifact[]) {}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* return an array of artifact objects.
|
|
12
|
-
*/
|
|
13
|
-
toArray() {
|
|
14
|
-
return this.artifacts;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* group artifacts by the storage resolver.
|
|
19
|
-
*/
|
|
20
|
-
groupByResolver(): ResolverMap {
|
|
21
|
-
const resolverMap: ResolverMap = {};
|
|
22
|
-
this.artifacts.forEach((artifact) => {
|
|
23
|
-
const storageResolver = artifact.storageResolver;
|
|
24
|
-
const resolverArray = resolverMap[storageResolver.name];
|
|
25
|
-
if (!resolverArray) {
|
|
26
|
-
resolverMap[storageResolver.name] = [artifact];
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
if (resolverArray.length) {
|
|
30
|
-
resolverMap[storageResolver.name].push(artifact);
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
return resolverMap;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
toObject(): ArtifactObject[] {
|
|
38
|
-
return this.artifacts.map((artifact) => artifact.toObject());
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
groupByTaskId() {
|
|
42
|
-
return this.artifacts.reduce((acc: { [key: string]: Artifact }, artifact) => {
|
|
43
|
-
const taskId = artifact.task.aspectId;
|
|
44
|
-
acc[taskId] = artifact;
|
|
45
|
-
return acc;
|
|
46
|
-
}, {});
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* store all artifacts using the configured storage resolvers.
|
|
51
|
-
*/
|
|
52
|
-
async store(component: Component) {
|
|
53
|
-
const byResolvers = this.groupByResolver();
|
|
54
|
-
const promises = Object.keys(byResolvers).map(async (key) => {
|
|
55
|
-
const artifacts = byResolvers[key];
|
|
56
|
-
if (!artifacts.length) return;
|
|
57
|
-
const storageResolver = artifacts[0].storageResolver;
|
|
58
|
-
const artifactList = new ArtifactList(artifacts);
|
|
59
|
-
await storageResolver.store(component, artifactList);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
return Promise.all(promises);
|
|
63
|
-
}
|
|
64
|
-
}
|
package/artifact/artifact.ts
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import type { ArtifactFiles, ArtifactObject } from '@teambit/legacy/dist/consumer/component/sources/artifact-files';
|
|
2
|
-
import type { BuildTask } from '../build-task';
|
|
3
|
-
import type { StorageResolver } from '../storage';
|
|
4
|
-
import type { ArtifactDefinition } from './artifact-definition';
|
|
5
|
-
|
|
6
|
-
export class Artifact {
|
|
7
|
-
constructor(
|
|
8
|
-
/**
|
|
9
|
-
* definition of the artifact.
|
|
10
|
-
*/
|
|
11
|
-
readonly def: ArtifactDefinition,
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* storage resolver. can be used to replace where artifacts are stored.
|
|
15
|
-
*/
|
|
16
|
-
readonly storageResolver: StorageResolver,
|
|
17
|
-
|
|
18
|
-
readonly files: ArtifactFiles,
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* join this with `this.paths` to get the absolute paths
|
|
22
|
-
*/
|
|
23
|
-
readonly rootDir: string,
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* the declaring task.
|
|
27
|
-
* todo: change this to taskDescriptor that has only the metadata of the task, so it could be
|
|
28
|
-
* saved into the model.
|
|
29
|
-
*/
|
|
30
|
-
readonly task: BuildTask,
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* timestamp of the artifact creation.
|
|
34
|
-
*/
|
|
35
|
-
readonly timestamp: number = Date.now()
|
|
36
|
-
) {}
|
|
37
|
-
|
|
38
|
-
get storage() {
|
|
39
|
-
return this.storageResolver;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* name of the artifact.
|
|
44
|
-
*/
|
|
45
|
-
get name(): string {
|
|
46
|
-
return this.def.name;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* description of the artifact.
|
|
51
|
-
*/
|
|
52
|
-
get description() {
|
|
53
|
-
return this.def.description;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* aspect id (string) that generated the artifact
|
|
58
|
-
*/
|
|
59
|
-
get generatedBy(): string {
|
|
60
|
-
return this.def.generatedBy || this.task.aspectId;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* archive all artifact files into a tar.
|
|
65
|
-
*/
|
|
66
|
-
tar() {}
|
|
67
|
-
|
|
68
|
-
toObject(): ArtifactObject {
|
|
69
|
-
return {
|
|
70
|
-
name: this.name,
|
|
71
|
-
description: this.description,
|
|
72
|
-
generatedBy: this.generatedBy,
|
|
73
|
-
storage: this.storageResolver.name,
|
|
74
|
-
task: {
|
|
75
|
-
id: this.task.aspectId,
|
|
76
|
-
name: this.task.name,
|
|
77
|
-
},
|
|
78
|
-
files: this.files,
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { Command, CommandOptions } from '@teambit/cli';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import { ScopeMain } from '@teambit/scope';
|
|
4
|
-
import { BuilderMain } from '../builder.main.runtime';
|
|
5
|
-
import { ArtifactExtractor, ExtractorArtifactResult, ExtractorResultGrouped } from './artifact-extractor';
|
|
6
|
-
|
|
7
|
-
const INDENT_TITLE = ' '.repeat(2);
|
|
8
|
-
const INDENT_SUB_TITLE = ' '.repeat(4);
|
|
9
|
-
const INDENT_FILES = ' '.repeat(6);
|
|
10
|
-
|
|
11
|
-
export type ArtifactsOpts = {
|
|
12
|
-
aspect?: string;
|
|
13
|
-
task?: string;
|
|
14
|
-
files?: string;
|
|
15
|
-
outDir?: string;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export class ArtifactsCmd implements Command {
|
|
19
|
-
name = 'artifacts <pattern...>';
|
|
20
|
-
shortDescription = 'EXPERIMENTAL. list and download components artifacts';
|
|
21
|
-
description = `EXPERIMENTAL. list and download components artifacts.
|
|
22
|
-
artifacts are created on isolated capsules during tag or snap commands.
|
|
23
|
-
example of artifacts are dists files generated by a compiler, a JUnit.xml file generated by a tester
|
|
24
|
-
and a package.tgz file generated by pkg aspect.
|
|
25
|
-
`;
|
|
26
|
-
alias = '';
|
|
27
|
-
group = 'development';
|
|
28
|
-
options = [
|
|
29
|
-
['', 'aspect <aspect-id>', 'show/download only artifacts generated by this aspect-id'],
|
|
30
|
-
['', 'task <task-id>', 'show/download only artifacts generated by this task-id'],
|
|
31
|
-
[
|
|
32
|
-
'',
|
|
33
|
-
'files <glob>',
|
|
34
|
-
'show/download only artifacts matching the given files or the glob pattern (wrap glob patterns in quotes)',
|
|
35
|
-
],
|
|
36
|
-
['', 'out-dir <string>', 'download the files to the specified dir'],
|
|
37
|
-
] as CommandOptions;
|
|
38
|
-
|
|
39
|
-
constructor(private builder: BuilderMain, private scope: ScopeMain) {}
|
|
40
|
-
|
|
41
|
-
async report([userPattern]: [string[]], artifactsOpts: ArtifactsOpts): Promise<string> {
|
|
42
|
-
const artifactExtractor = new ArtifactExtractor(this.scope, this.builder, userPattern, artifactsOpts);
|
|
43
|
-
const list = await artifactExtractor.list();
|
|
44
|
-
const grouped = artifactExtractor.groupResultsByAspect(list);
|
|
45
|
-
const outputArtifacts = (aspectId: string, artifactData: ExtractorArtifactResult[]) => {
|
|
46
|
-
const title = chalk.green(aspectId);
|
|
47
|
-
const artifactDataStr = artifactData
|
|
48
|
-
.map((artifact) => {
|
|
49
|
-
const subTitle = chalk.white(artifact.taskName);
|
|
50
|
-
const files = artifact.files.map((f) => INDENT_FILES + chalk.dim(f)).join('\n');
|
|
51
|
-
return `${INDENT_SUB_TITLE}${subTitle}\n${files}`;
|
|
52
|
-
})
|
|
53
|
-
.join('\n');
|
|
54
|
-
return `${INDENT_TITLE}${title}\n${artifactDataStr}`;
|
|
55
|
-
};
|
|
56
|
-
const outputResult = (result: ExtractorResultGrouped) => {
|
|
57
|
-
const idStr = chalk.cyan(result.id.toString());
|
|
58
|
-
const artifacts = Object.keys(result.artifacts)
|
|
59
|
-
.map((aspectId) => outputArtifacts(aspectId, result.artifacts[aspectId]))
|
|
60
|
-
.join('\n\n');
|
|
61
|
-
return `${idStr}\n${artifacts}`;
|
|
62
|
-
};
|
|
63
|
-
const footer = artifactsOpts.outDir
|
|
64
|
-
? chalk.green('\n\nThe above files were saved successfully to the file system')
|
|
65
|
-
: '';
|
|
66
|
-
return grouped.map(outputResult).join('\n\n') + footer;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { AspectDescriptor } from '@teambit/aspect-loader';
|
|
2
|
-
import { AbstractVinyl } from '@teambit/legacy/dist/consumer/component/sources';
|
|
3
|
-
|
|
4
|
-
export class ExtensionArtifact {
|
|
5
|
-
constructor(readonly files: AbstractVinyl[], readonly extensionDescriptor: AspectDescriptor) {}
|
|
6
|
-
|
|
7
|
-
toObject() {
|
|
8
|
-
return {
|
|
9
|
-
extensionDescriptor: this.extensionDescriptor,
|
|
10
|
-
};
|
|
11
|
-
}
|
|
12
|
-
}
|
package/artifact/index.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
export { ArtifactDefinition } from './artifact-definition';
|
|
2
|
-
export { ExtensionArtifact } from './extension-artifact';
|
|
3
|
-
export { Artifact } from './artifact';
|
|
4
|
-
export { ArtifactList } from './artifact-list';
|
|
5
|
-
export { ArtifactFactory, ArtifactMap } from './artifact-factory';
|
package/build-pipe.ts
DELETED
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import { EnvDefinition } from '@teambit/envs';
|
|
2
|
-
import { ComponentMap } from '@teambit/component';
|
|
3
|
-
import { Logger, LongProcessLogger } from '@teambit/logger';
|
|
4
|
-
import mapSeries from 'p-map-series';
|
|
5
|
-
import prettyTime from 'pretty-time';
|
|
6
|
-
import { ArtifactFactory, ArtifactList } from './artifact';
|
|
7
|
-
import { BuildTask, BuildTaskHelper } from './build-task';
|
|
8
|
-
import { ComponentResult } from './types';
|
|
9
|
-
import { TasksQueue } from './tasks-queue';
|
|
10
|
-
import { EnvsBuildContext } from './builder.service';
|
|
11
|
-
import { TaskResultsList } from './task-results-list';
|
|
12
|
-
|
|
13
|
-
export type TaskResults = {
|
|
14
|
-
/**
|
|
15
|
-
* task itself. useful for getting its id/description later on.
|
|
16
|
-
*/
|
|
17
|
-
task: BuildTask;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* environment were the task was running
|
|
21
|
-
*/
|
|
22
|
-
env: EnvDefinition;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* component build results.
|
|
26
|
-
*/
|
|
27
|
-
componentsResults: ComponentResult[];
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* artifacts generated by the build pipeline.
|
|
31
|
-
* in case the task finished with errors, this prop is undefined.
|
|
32
|
-
*/
|
|
33
|
-
artifacts: ComponentMap<ArtifactList> | undefined;
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* timestamp of start initiation.
|
|
37
|
-
*/
|
|
38
|
-
startTime: number;
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* timestamp of task completion.
|
|
42
|
-
*/
|
|
43
|
-
endTime: number;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export class BuildPipe {
|
|
47
|
-
private failedTasks: BuildTask[] = [];
|
|
48
|
-
private failedDependencyTask: BuildTask | undefined;
|
|
49
|
-
private longProcessLogger: LongProcessLogger;
|
|
50
|
-
private taskResults: TaskResults[] = [];
|
|
51
|
-
constructor(
|
|
52
|
-
/**
|
|
53
|
-
* array of services to apply on the components.
|
|
54
|
-
*/
|
|
55
|
-
readonly tasksQueue: TasksQueue,
|
|
56
|
-
readonly envsBuildContext: EnvsBuildContext,
|
|
57
|
-
readonly logger: Logger,
|
|
58
|
-
readonly artifactFactory: ArtifactFactory
|
|
59
|
-
) {}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* execute a pipeline of build tasks.
|
|
63
|
-
*/
|
|
64
|
-
async execute(): Promise<TaskResultsList> {
|
|
65
|
-
await this.executePreBuild();
|
|
66
|
-
this.longProcessLogger = this.logger.createLongProcessLogger('running tasks', this.tasksQueue.length);
|
|
67
|
-
await mapSeries(this.tasksQueue, async ({ task, env }) => this.executeTask(task, env));
|
|
68
|
-
this.longProcessLogger.end();
|
|
69
|
-
const tasksResultsList = new TaskResultsList(this.tasksQueue, this.taskResults);
|
|
70
|
-
await this.executePostBuild(tasksResultsList);
|
|
71
|
-
|
|
72
|
-
return tasksResultsList;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
private async executePreBuild() {
|
|
76
|
-
this.logger.setStatusLine('executing pre-build for all tasks');
|
|
77
|
-
await mapSeries(this.tasksQueue, async ({ task, env }) => {
|
|
78
|
-
if (!task.preBuild) return;
|
|
79
|
-
await task.preBuild(this.getBuildContext(env.id));
|
|
80
|
-
});
|
|
81
|
-
this.logger.consoleSuccess();
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
private async executeTask(task: BuildTask, env: EnvDefinition): Promise<void> {
|
|
85
|
-
const taskId = BuildTaskHelper.serializeId(task);
|
|
86
|
-
const taskName = `${taskId}${task.description ? ` (${task.description})` : ''}`;
|
|
87
|
-
this.longProcessLogger.logProgress(`env "${env.id}", task "${taskName}"`);
|
|
88
|
-
this.updateFailedDependencyTask(task);
|
|
89
|
-
if (this.shouldSkipTask(taskId, env.id)) {
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
const startTask = process.hrtime();
|
|
93
|
-
const taskStartTime = Date.now();
|
|
94
|
-
const buildContext = this.getBuildContext(env.id);
|
|
95
|
-
const buildTaskResult = await task.execute(buildContext);
|
|
96
|
-
const endTime = Date.now();
|
|
97
|
-
const compsWithErrors = buildTaskResult.componentsResults.filter((c) => c.errors?.length);
|
|
98
|
-
let artifacts;
|
|
99
|
-
if (compsWithErrors.length) {
|
|
100
|
-
this.logger.consoleFailure(`env: ${env.id}, task "${taskId}" has failed`);
|
|
101
|
-
this.failedTasks.push(task);
|
|
102
|
-
} else {
|
|
103
|
-
const duration = prettyTime(process.hrtime(startTask));
|
|
104
|
-
this.logger.consoleSuccess(`env "${env.id}", task "${taskName}" has completed successfully in ${duration}`);
|
|
105
|
-
const defs = buildTaskResult.artifacts || [];
|
|
106
|
-
artifacts = this.artifactFactory.generate(buildContext, defs, task);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const taskResults: TaskResults = {
|
|
110
|
-
task,
|
|
111
|
-
env,
|
|
112
|
-
componentsResults: buildTaskResult.componentsResults,
|
|
113
|
-
artifacts,
|
|
114
|
-
startTime: taskStartTime,
|
|
115
|
-
endTime,
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
this.taskResults.push(taskResults);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
private async executePostBuild(tasksResults: TaskResultsList) {
|
|
122
|
-
this.logger.setStatusLine('executing post-build for all tasks');
|
|
123
|
-
await mapSeries(this.tasksQueue, async ({ task, env }) => {
|
|
124
|
-
if (!task.postBuild) return;
|
|
125
|
-
await task.postBuild(this.getBuildContext(env.id), tasksResults);
|
|
126
|
-
});
|
|
127
|
-
this.logger.consoleSuccess();
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
private updateFailedDependencyTask(task: BuildTask) {
|
|
131
|
-
if (!this.failedDependencyTask && this.failedTasks.length && task.dependencies) {
|
|
132
|
-
task.dependencies.forEach((dependency) => {
|
|
133
|
-
const { aspectId, name } = BuildTaskHelper.deserializeId(dependency);
|
|
134
|
-
this.failedDependencyTask = this.failedTasks.find((failedTask) => {
|
|
135
|
-
if (name && name !== failedTask.name) return false;
|
|
136
|
-
return aspectId === failedTask.aspectId;
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
private shouldSkipTask(taskId: string, envId: string): boolean {
|
|
143
|
-
if (!this.failedDependencyTask) return false;
|
|
144
|
-
const failedTaskId = BuildTaskHelper.serializeId(this.failedDependencyTask);
|
|
145
|
-
this.logger.consoleWarning(`env: ${envId}, task "${taskId}" has skipped due to "${failedTaskId}" failure`);
|
|
146
|
-
return true;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
private getBuildContext(envId: string) {
|
|
150
|
-
const buildContext = this.envsBuildContext[envId];
|
|
151
|
-
if (!buildContext) throw new Error(`unable to find buildContext for ${envId}`);
|
|
152
|
-
buildContext.previousTasksResults = this.taskResults;
|
|
153
|
-
return buildContext;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* create a build pipe from an array of tasks.
|
|
158
|
-
*/
|
|
159
|
-
static from(
|
|
160
|
-
tasksQueue: TasksQueue,
|
|
161
|
-
envsBuildContext: EnvsBuildContext,
|
|
162
|
-
logger: Logger,
|
|
163
|
-
artifactFactory: ArtifactFactory
|
|
164
|
-
) {
|
|
165
|
-
return new BuildPipe(tasksQueue, envsBuildContext, logger, artifactFactory);
|
|
166
|
-
}
|
|
167
|
-
}
|