@teambit/builder 1.0.108 → 1.0.110
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/preview/teambit_pipelines_builder-preview.js +1 -0
- package/dist/{preview-1703647408454.js → preview-1703733956734.js} +2 -2
- package/package.json +26 -22
- package/build-pipe.ts +0 -216
- package/build-pipeline-order.ts +0 -192
- package/build-pipeline-result-list.ts +0 -97
- package/build-task.ts +0 -151
- package/build.cmd.ts +0 -157
- package/builder-env-type.ts +0 -16
- package/builder.aspect.ts +0 -5
- package/builder.graphql.ts +0 -185
- package/builder.main.runtime.ts +0 -493
- package/builder.route.ts +0 -95
- package/index.ts +0 -20
- package/pipeline.ts +0 -104
- package/task-results-list.ts +0 -68
- package/task.ts +0 -50
- package/tasks-queue.ts +0 -40
- package/types.ts +0 -37
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { ComponentID, ComponentMap, Component } from '@teambit/component';
|
|
2
|
-
import { isEmpty, compact } from 'lodash';
|
|
3
|
-
import type { ArtifactObject } from '@teambit/legacy/dist/consumer/component/sources/artifact-files';
|
|
4
|
-
import { Artifact, ArtifactList } from './artifact';
|
|
5
|
-
import { TaskResults } from './build-pipe';
|
|
6
|
-
import { TaskMetadata } from './types';
|
|
7
|
-
|
|
8
|
-
export type PipelineReport = {
|
|
9
|
-
taskId: string; // task aspect-id
|
|
10
|
-
taskName: string;
|
|
11
|
-
taskDescription?: string;
|
|
12
|
-
startTime?: number;
|
|
13
|
-
endTime?: number;
|
|
14
|
-
errors?: Array<Error | string>;
|
|
15
|
-
warnings?: string[];
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export type AspectData = {
|
|
19
|
-
aspectId: string;
|
|
20
|
-
data: TaskMetadata;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Helper to get the data and artifacts from the TasksResultsList before saving during the tag
|
|
25
|
-
*/
|
|
26
|
-
export class BuildPipelineResultList {
|
|
27
|
-
private artifactListsMap: ComponentMap<ArtifactList<Artifact>>;
|
|
28
|
-
constructor(private tasksResults: TaskResults[], private components: Component[]) {
|
|
29
|
-
this.artifactListsMap = this.getFlattenedArtifactListsMapFromAllTasks();
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
private getFlattenedArtifactListsMapFromAllTasks(): ComponentMap<ArtifactList<Artifact>> {
|
|
33
|
-
const artifactListsMaps = this.tasksResults.flatMap((t) => (t.artifacts ? [t.artifacts] : []));
|
|
34
|
-
return ComponentMap.as<ArtifactList<Artifact>>(this.components, (component) => {
|
|
35
|
-
const artifacts: Artifact[] = [];
|
|
36
|
-
artifactListsMaps.forEach((artifactListMap) => {
|
|
37
|
-
const artifactList = artifactListMap.getValueByComponentId(component.id);
|
|
38
|
-
if (artifactList) artifacts.push(...artifactList);
|
|
39
|
-
});
|
|
40
|
-
return ArtifactList.fromArray(artifacts);
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
public getMetadataFromTaskResults(componentId: ComponentID): { [taskId: string]: TaskMetadata } {
|
|
45
|
-
const compResults = this.tasksResults.reduce((acc, current: TaskResults) => {
|
|
46
|
-
const foundComponent = current.componentsResults.find((c) => c.component.id.isEqual(componentId));
|
|
47
|
-
const taskId = current.task.aspectId;
|
|
48
|
-
if (foundComponent && foundComponent.metadata) {
|
|
49
|
-
acc[taskId] = this.mergeDataIfPossible(foundComponent.metadata, acc[taskId], taskId);
|
|
50
|
-
}
|
|
51
|
-
return acc;
|
|
52
|
-
}, {});
|
|
53
|
-
return compResults;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
public getPipelineReportOfComponent(componentId: ComponentID): PipelineReport[] {
|
|
57
|
-
const compResults = this.tasksResults.map((taskResults: TaskResults) => {
|
|
58
|
-
const foundComponent = taskResults.componentsResults.find((c) => c.component.id.isEqual(componentId));
|
|
59
|
-
if (!foundComponent) return null;
|
|
60
|
-
const pipelineReport: PipelineReport = {
|
|
61
|
-
taskId: taskResults.task.aspectId,
|
|
62
|
-
taskName: taskResults.task.name,
|
|
63
|
-
taskDescription: taskResults.task.description,
|
|
64
|
-
errors: foundComponent.errors,
|
|
65
|
-
warnings: foundComponent.warnings,
|
|
66
|
-
startTime: foundComponent.startTime,
|
|
67
|
-
endTime: foundComponent.endTime,
|
|
68
|
-
};
|
|
69
|
-
return pipelineReport;
|
|
70
|
-
});
|
|
71
|
-
return compact(compResults);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
public getDataOfComponent(componentId: ComponentID): AspectData[] {
|
|
75
|
-
const tasksData = this.getMetadataFromTaskResults(componentId);
|
|
76
|
-
return Object.keys(tasksData).map((taskId) => ({
|
|
77
|
-
aspectId: taskId,
|
|
78
|
-
data: tasksData[taskId],
|
|
79
|
-
}));
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
public getArtifactsDataOfComponent(componentId: ComponentID): ArtifactObject[] | undefined {
|
|
83
|
-
return this.artifactListsMap.getValueByComponentId(componentId)?.toObject();
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
private mergeDataIfPossible(currentData: TaskMetadata, existingData: TaskMetadata | undefined, taskId: string) {
|
|
87
|
-
if (!existingData || isEmpty(existingData)) return currentData;
|
|
88
|
-
// both exist
|
|
89
|
-
if (typeof currentData !== 'object') {
|
|
90
|
-
throw new Error(`task data must be "object", get ${typeof currentData} for ${taskId}`);
|
|
91
|
-
}
|
|
92
|
-
if (Array.isArray(currentData)) {
|
|
93
|
-
throw new Error(`task data must be "object", get Array for ${taskId}`);
|
|
94
|
-
}
|
|
95
|
-
return { ...currentData, ...existingData };
|
|
96
|
-
}
|
|
97
|
-
}
|
package/build-task.ts
DELETED
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
import type { Component } from '@teambit/component';
|
|
2
|
-
import { LaneId } from '@teambit/lane-id';
|
|
3
|
-
import { ExecutionContext } from '@teambit/envs';
|
|
4
|
-
import type { Network } from '@teambit/isolator';
|
|
5
|
-
import type { ComponentResult } from './types';
|
|
6
|
-
import type { ArtifactDefinition } from './artifact';
|
|
7
|
-
import { TaskResultsList } from './task-results-list';
|
|
8
|
-
import { TaskResults } from './build-pipe';
|
|
9
|
-
import { PipeName } from './builder.service';
|
|
10
|
-
|
|
11
|
-
export type TaskLocation = 'start' | 'end';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* delimiter between task.aspectId and task.name
|
|
15
|
-
*/
|
|
16
|
-
export const TaskIdDelimiter = ':';
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* A folder to write artifacts generated during a build task
|
|
20
|
-
* This folder is used in the core envs and excluded by default from the package tar file (the core envs is writing this into the npmignore file)
|
|
21
|
-
*/
|
|
22
|
-
export const CAPSULE_ARTIFACTS_DIR = 'artifacts';
|
|
23
|
-
|
|
24
|
-
export interface BuildContext extends ExecutionContext {
|
|
25
|
-
/**
|
|
26
|
-
* all components about to be built/tagged.
|
|
27
|
-
*/
|
|
28
|
-
components: Component[];
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* network of capsules ready to be built.
|
|
32
|
-
*/
|
|
33
|
-
capsuleNetwork: Network;
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* data generated by tasks that were running before this task
|
|
37
|
-
*/
|
|
38
|
-
previousTasksResults: TaskResults[];
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Run the build pipeline in dev mode
|
|
42
|
-
*/
|
|
43
|
-
dev?: boolean;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* pipe name such as "build", "tas", "snap".
|
|
47
|
-
* an example usage is "deploy" task which is running in snap and tag pipeline and has different needs in each one.
|
|
48
|
-
*/
|
|
49
|
-
pipeName: PipeName;
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* current lane-id if exists. empty when on main.
|
|
53
|
-
*/
|
|
54
|
-
laneId?: LaneId;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export interface TaskDescriptor {
|
|
58
|
-
aspectId: string;
|
|
59
|
-
name?: string;
|
|
60
|
-
description?: string;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export interface BuildTask {
|
|
64
|
-
/**
|
|
65
|
-
* aspect id serialized of the creator of the task.
|
|
66
|
-
* todo: automate this so then it won't be needed to pass manually.
|
|
67
|
-
*/
|
|
68
|
-
aspectId: string;
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* name of the task. function as an identifier among other tasks of the same aspectId.
|
|
72
|
-
* spaces and special characters are not allowed. as a convention, use UpperCamelCase style.
|
|
73
|
-
* (e.g. TypescriptCompiler).
|
|
74
|
-
*/
|
|
75
|
-
name: string;
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* description of what the task does.
|
|
79
|
-
* if available, the logger will log it show it in the status-line.
|
|
80
|
-
*/
|
|
81
|
-
description?: string;
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* where to put the task, before the env pipeline or after
|
|
85
|
-
*/
|
|
86
|
-
location?: TaskLocation;
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* execute a task in a build context
|
|
90
|
-
*/
|
|
91
|
-
execute(context: BuildContext): Promise<BuiltTaskResult>;
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* run before the build pipeline has started. this is useful when some preparation are needed to
|
|
95
|
-
* be done on all envs before the build starts.
|
|
96
|
-
* e.g. typescript compiler needs to write the tsconfig file. doing it during the task, will
|
|
97
|
-
* cause dependencies from other envs to get this tsconfig written.
|
|
98
|
-
*/
|
|
99
|
-
preBuild?(context: BuildContext): Promise<void>;
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* run after the build pipeline completed for all envs. useful for doing some cleanup on the
|
|
103
|
-
* capsules before the deployment starts.
|
|
104
|
-
*/
|
|
105
|
-
postBuild?(context: BuildContext, tasksResults: TaskResultsList): Promise<void>;
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* needed if you want the task to be running only after the dependencies were completed
|
|
109
|
-
* for *all* envs.
|
|
110
|
-
* normally this is not needed because the build-pipeline runs the tasks in the same order
|
|
111
|
-
* they're located in the `getBuildPipe()` array and according to the task.location.
|
|
112
|
-
* the case where this is useful is when a task not only needs to be after another task, but also
|
|
113
|
-
* after all environments were running that task.
|
|
114
|
-
* a dependency is task.aspectId. if an aspect has multiple tasks, to be more specific, use
|
|
115
|
-
* "aspectId:name", e.g. "teambit.compilation/compiler:TypescriptCompiler".
|
|
116
|
-
*/
|
|
117
|
-
dependencies?: string[];
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// TODO: rename to BuildTaskResults
|
|
121
|
-
export interface BuiltTaskResult {
|
|
122
|
-
/**
|
|
123
|
-
* build results for each of the components in the build context.
|
|
124
|
-
*/
|
|
125
|
-
componentsResults: ComponentResult[];
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* array of artifact definitions to generate after a successful build.
|
|
129
|
-
*/
|
|
130
|
-
artifacts?: ArtifactDefinition[];
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export class BuildTaskHelper {
|
|
134
|
-
static serializeId({ aspectId, name }: { aspectId: string; name: string }): string {
|
|
135
|
-
return aspectId + TaskIdDelimiter + name;
|
|
136
|
-
}
|
|
137
|
-
static deserializeId(id: string): { aspectId: string; name: string } {
|
|
138
|
-
const split = id.split(TaskIdDelimiter);
|
|
139
|
-
if (split.length === 0) throw new Error(`deserializeId, ${id} is empty`);
|
|
140
|
-
if (split.length === 1) throw new Error(`deserializeId, ${id} has only aspect-id without name`);
|
|
141
|
-
if (split.length === 2) return { aspectId: split[0], name: split[1] };
|
|
142
|
-
throw new Error(`deserializeId, id ${id} has more than one ${TaskIdDelimiter}`);
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* don't throw an error when the id includes only the aspect-id without the task name.
|
|
146
|
-
* useful for task dependencies, when it's allowed to specify the aspect-id only.
|
|
147
|
-
*/
|
|
148
|
-
static deserializeIdAllowEmptyName(id: string): { aspectId: string; name?: string } {
|
|
149
|
-
return id.includes(TaskIdDelimiter) ? BuildTaskHelper.deserializeId(id) : { aspectId: id, name: undefined };
|
|
150
|
-
}
|
|
151
|
-
}
|
package/build.cmd.ts
DELETED
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import { Command, CommandOptions } from '@teambit/cli';
|
|
2
|
-
import { Logger } from '@teambit/logger';
|
|
3
|
-
import prettyTime from 'pretty-time';
|
|
4
|
-
import { OutsideWorkspaceError, Workspace } from '@teambit/workspace';
|
|
5
|
-
import { COMPONENT_PATTERN_HELP } from '@teambit/legacy/dist/constants';
|
|
6
|
-
import chalk from 'chalk';
|
|
7
|
-
import { BuilderMain } from './builder.main.runtime';
|
|
8
|
-
|
|
9
|
-
type BuildOpts = {
|
|
10
|
-
all: boolean; // deprecated. use unmodified
|
|
11
|
-
unmodified?: boolean;
|
|
12
|
-
dev: boolean;
|
|
13
|
-
rebuild: boolean;
|
|
14
|
-
install: boolean;
|
|
15
|
-
cachePackagesOnCapsulesRoot: boolean;
|
|
16
|
-
reuseCapsules: boolean;
|
|
17
|
-
tasks: string;
|
|
18
|
-
listTasks?: string;
|
|
19
|
-
skipTests?: boolean;
|
|
20
|
-
failFast?: boolean;
|
|
21
|
-
includeSnap?: boolean;
|
|
22
|
-
includeTag?: boolean;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export class BuilderCmd implements Command {
|
|
26
|
-
name = 'build [component-pattern]';
|
|
27
|
-
description = 'run set of tasks for build.';
|
|
28
|
-
extendedDescription = 'by default, only new and modified components are built';
|
|
29
|
-
arguments = [{ name: 'component-pattern', description: COMPONENT_PATTERN_HELP }];
|
|
30
|
-
helpUrl = 'reference/build-pipeline/builder-overview';
|
|
31
|
-
alias = '';
|
|
32
|
-
group = 'development';
|
|
33
|
-
options = [
|
|
34
|
-
['a', 'all', 'DEPRECATED. use --unmodified'],
|
|
35
|
-
['u', 'unmodified', 'include unmodified components (by default, only new and modified components are built)'],
|
|
36
|
-
['d', 'dev', 'run the pipeline in dev mode'],
|
|
37
|
-
['', 'install', 'install core aspects in capsules'],
|
|
38
|
-
['', 'reuse-capsules', 'avoid deleting the capsules root-dir before starting the build'],
|
|
39
|
-
[
|
|
40
|
-
'',
|
|
41
|
-
'tasks <string>',
|
|
42
|
-
`build the specified task(s) only. for multiple tasks, separate by a comma and wrap with quotes.
|
|
43
|
-
specify the task-name (e.g. "TypescriptCompiler") or the task-aspect-id (e.g. teambit.compilation/compiler)`,
|
|
44
|
-
],
|
|
45
|
-
['', 'cache-packages-on-capsule-root', 'set the package-manager cache on the capsule root'],
|
|
46
|
-
[
|
|
47
|
-
'',
|
|
48
|
-
'list-tasks <string>',
|
|
49
|
-
'list tasks of an env or a component-id for each one of the pipelines: build, tag and snap',
|
|
50
|
-
],
|
|
51
|
-
['', 'skip-tests', 'skip running component tests during build process'],
|
|
52
|
-
[
|
|
53
|
-
'',
|
|
54
|
-
'fail-fast',
|
|
55
|
-
'stop pipeline execution on the first failed task (by default a task is skipped only when its dependency failed)',
|
|
56
|
-
],
|
|
57
|
-
[
|
|
58
|
-
'',
|
|
59
|
-
'include-snap',
|
|
60
|
-
'EXPERIMENTAL. include snap pipeline tasks. Warning: this may deploy/publish if you have such tasks',
|
|
61
|
-
],
|
|
62
|
-
[
|
|
63
|
-
'',
|
|
64
|
-
'include-tag',
|
|
65
|
-
'EXPERIMENTAL. include tag pipeline tasks. Warning: this may deploy/publish if you have such tasks',
|
|
66
|
-
],
|
|
67
|
-
] as CommandOptions;
|
|
68
|
-
|
|
69
|
-
constructor(private builder: BuilderMain, private workspace: Workspace, private logger: Logger) {}
|
|
70
|
-
|
|
71
|
-
async report(
|
|
72
|
-
[pattern]: [string],
|
|
73
|
-
{
|
|
74
|
-
all = false,
|
|
75
|
-
unmodified = false,
|
|
76
|
-
dev = false,
|
|
77
|
-
install = false,
|
|
78
|
-
cachePackagesOnCapsulesRoot = false,
|
|
79
|
-
reuseCapsules = false,
|
|
80
|
-
tasks,
|
|
81
|
-
listTasks,
|
|
82
|
-
skipTests,
|
|
83
|
-
failFast,
|
|
84
|
-
includeSnap,
|
|
85
|
-
includeTag,
|
|
86
|
-
}: BuildOpts
|
|
87
|
-
): Promise<string> {
|
|
88
|
-
if (!this.workspace) throw new OutsideWorkspaceError();
|
|
89
|
-
if (all) {
|
|
90
|
-
this.logger.consoleWarning(`--all is deprecated, please use --unmodified instead`);
|
|
91
|
-
unmodified = true;
|
|
92
|
-
}
|
|
93
|
-
if (listTasks) {
|
|
94
|
-
return this.getListTasks(listTasks);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
this.logger.setStatusLine('build');
|
|
98
|
-
const start = process.hrtime();
|
|
99
|
-
const components = await this.workspace.getComponentsByUserInput(unmodified, pattern, true);
|
|
100
|
-
if (!components.length) {
|
|
101
|
-
return chalk.bold(
|
|
102
|
-
`no components found to build. use "--unmodified" flag to build all components or specify the ids to build, otherwise, only new and modified components will be built`
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const envsExecutionResults = await this.builder.build(
|
|
107
|
-
components,
|
|
108
|
-
{
|
|
109
|
-
installOptions: {
|
|
110
|
-
installTeambitBit: install,
|
|
111
|
-
packageManagerConfigRootDir: this.workspace.path,
|
|
112
|
-
},
|
|
113
|
-
linkingOptions: { linkTeambitBit: !install },
|
|
114
|
-
emptyRootDir: !reuseCapsules,
|
|
115
|
-
getExistingAsIs: reuseCapsules,
|
|
116
|
-
cachePackagesOnCapsulesRoot,
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
dev,
|
|
120
|
-
tasks: tasks ? tasks.split(',').map((task) => task.trim()) : [],
|
|
121
|
-
skipTests,
|
|
122
|
-
exitOnFirstFailedTask: failFast,
|
|
123
|
-
},
|
|
124
|
-
{
|
|
125
|
-
includeSnap,
|
|
126
|
-
includeTag,
|
|
127
|
-
}
|
|
128
|
-
);
|
|
129
|
-
this.logger.console(`build output can be found in path: ${envsExecutionResults.capsuleRootDir}`);
|
|
130
|
-
const duration = prettyTime(process.hrtime(start));
|
|
131
|
-
const succeedOrFailed = envsExecutionResults.hasErrors() ? 'failed' : 'succeeded';
|
|
132
|
-
const msg = `build ${succeedOrFailed}. completed in ${duration}.`;
|
|
133
|
-
if (envsExecutionResults.hasErrors()) {
|
|
134
|
-
this.logger.consoleFailure(msg);
|
|
135
|
-
}
|
|
136
|
-
envsExecutionResults.throwErrorsIfExist();
|
|
137
|
-
return chalk.green(msg);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
private async getListTasks(componentIdStr: string): Promise<string> {
|
|
141
|
-
const compId = await this.workspace.resolveComponentId(componentIdStr);
|
|
142
|
-
const component = await this.workspace.get(compId);
|
|
143
|
-
const results = this.builder.listTasks(component);
|
|
144
|
-
return `${chalk.green('Task List')}
|
|
145
|
-
id: ${results.id.toString()}
|
|
146
|
-
envId: ${results.envId}
|
|
147
|
-
|
|
148
|
-
${chalk.bold('Build Pipeline Tasks:')}
|
|
149
|
-
${results.buildTasks.join('\n')}
|
|
150
|
-
|
|
151
|
-
${chalk.bold('Tag Pipeline Tasks:')}
|
|
152
|
-
${results.tagTasks.join('\n')}
|
|
153
|
-
|
|
154
|
-
${chalk.bold('Snap Pipeline Tasks:')}
|
|
155
|
-
${results.snapTasks.join('\n') || '<N/A>'}`;
|
|
156
|
-
}
|
|
157
|
-
}
|
package/builder-env-type.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { Pipeline } from './pipeline';
|
|
2
|
-
|
|
3
|
-
export interface BuilderEnv {
|
|
4
|
-
/**
|
|
5
|
-
* return a build pipeline instance.
|
|
6
|
-
*/
|
|
7
|
-
build(): Pipeline;
|
|
8
|
-
/**
|
|
9
|
-
* return a snap pipeline instance.
|
|
10
|
-
*/
|
|
11
|
-
snap(): Pipeline;
|
|
12
|
-
/**
|
|
13
|
-
* return a tag pipeline instance.
|
|
14
|
-
*/
|
|
15
|
-
tag(): Pipeline;
|
|
16
|
-
}
|
package/builder.aspect.ts
DELETED
package/builder.graphql.ts
DELETED
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
import { Component, ComponentID } from '@teambit/component';
|
|
2
|
-
import gql from 'graphql-tag';
|
|
3
|
-
import { Logger } from '@teambit/logger';
|
|
4
|
-
import isBinaryPath from 'is-binary-path';
|
|
5
|
-
import { BuilderMain } from './builder.main.runtime';
|
|
6
|
-
import { PipelineReport } from './build-pipeline-result-list';
|
|
7
|
-
|
|
8
|
-
type ArtifactGQLFile = {
|
|
9
|
-
/**
|
|
10
|
-
* same as the path - used for GQL caching
|
|
11
|
-
*/
|
|
12
|
-
id: string;
|
|
13
|
-
/**
|
|
14
|
-
* name of the artifact file
|
|
15
|
-
*/
|
|
16
|
-
name: string;
|
|
17
|
-
/**
|
|
18
|
-
* path of the artifact file
|
|
19
|
-
*/
|
|
20
|
-
path: string;
|
|
21
|
-
/**
|
|
22
|
-
* artifact file content (only for text files). Use /api/<component-id>/~aspect/builder/<extension-id>/~<path> to fetch binary file data
|
|
23
|
-
*/
|
|
24
|
-
content?: string;
|
|
25
|
-
/**
|
|
26
|
-
* REST endpoint to fetch artifact data from. /api/<component-id>/~aspect/builder/<extension-id>/~<pat
|
|
27
|
-
*/
|
|
28
|
-
downloadUrl?: string;
|
|
29
|
-
/**
|
|
30
|
-
* Remote storage url to resolve artifact file from
|
|
31
|
-
*/
|
|
32
|
-
externalUrl?: string;
|
|
33
|
-
/**
|
|
34
|
-
* Size in bytes
|
|
35
|
-
*/
|
|
36
|
-
size: number;
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
type ArtifactGQLData = {
|
|
40
|
-
name: string;
|
|
41
|
-
description?: string;
|
|
42
|
-
storage?: string;
|
|
43
|
-
generatedBy: string;
|
|
44
|
-
files: ArtifactGQLFile[];
|
|
45
|
-
};
|
|
46
|
-
type TaskReport = PipelineReport & {
|
|
47
|
-
artifact?: ArtifactGQLData;
|
|
48
|
-
componentId: ComponentID;
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
export function builderSchema(builder: BuilderMain, logger: Logger) {
|
|
52
|
-
return {
|
|
53
|
-
typeDefs: gql`
|
|
54
|
-
type TaskReport {
|
|
55
|
-
# for GQL caching - taskId + taskName
|
|
56
|
-
id: String!
|
|
57
|
-
taskId: String!
|
|
58
|
-
taskName: String!
|
|
59
|
-
description: String
|
|
60
|
-
startTime: String
|
|
61
|
-
endTime: String
|
|
62
|
-
errors: [String!]
|
|
63
|
-
warnings: [String!]
|
|
64
|
-
artifact(path: String): Artifact
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
type ArtifactFile {
|
|
68
|
-
# for GQL caching - same as the path
|
|
69
|
-
id: String!
|
|
70
|
-
# name of the artifact file
|
|
71
|
-
name: String
|
|
72
|
-
# path of the artifact file
|
|
73
|
-
path: String!
|
|
74
|
-
# artifact file content (only for text files). Use /api/<component-id>/~aspect/builder/<extension-id>/~<path> to fetch binary file data
|
|
75
|
-
content: String
|
|
76
|
-
# REST endpoint to fetch artifact data from. /api/<component-id>/~aspect/builder/<extension-id>/~<path>
|
|
77
|
-
downloadUrl: String
|
|
78
|
-
# Remote storage url to resolve artifact file from
|
|
79
|
-
externalUrl: String
|
|
80
|
-
# size in bytes
|
|
81
|
-
size: Int!
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
type Artifact {
|
|
85
|
-
# for GQL caching - PipelineId + Artifact Name
|
|
86
|
-
id: String!
|
|
87
|
-
# artifact name
|
|
88
|
-
name: String!
|
|
89
|
-
description: String
|
|
90
|
-
storage: String
|
|
91
|
-
generatedBy: String
|
|
92
|
-
files: [ArtifactFile!]!
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
extend type Component {
|
|
96
|
-
pipelineReport(taskId: String): [TaskReport!]!
|
|
97
|
-
}
|
|
98
|
-
`,
|
|
99
|
-
|
|
100
|
-
resolvers: {
|
|
101
|
-
Component: {
|
|
102
|
-
pipelineReport: async (component: Component, { taskId }: { taskId?: string }) => {
|
|
103
|
-
try {
|
|
104
|
-
const builderData = builder.getBuilderData(component);
|
|
105
|
-
const pipeline = builderData?.pipeline || [];
|
|
106
|
-
const artifacts = taskId
|
|
107
|
-
? builder.getArtifactsByAspect(component, taskId)
|
|
108
|
-
: builder.getArtifacts(component);
|
|
109
|
-
const artifactsWithVinyl = await Promise.all(
|
|
110
|
-
artifacts.map(async (artifact) => {
|
|
111
|
-
const id = artifact.task.aspectId;
|
|
112
|
-
const name = artifact.task.name as string;
|
|
113
|
-
try {
|
|
114
|
-
const artifactFiles = (await builder.getArtifactsVinylByAspectAndTaskName(component, id, name)).map(
|
|
115
|
-
(vinyl) => {
|
|
116
|
-
const { basename, path, contents } = vinyl || {};
|
|
117
|
-
const isBinary = path && isBinaryPath(path);
|
|
118
|
-
const content = !isBinary ? contents?.toString('utf-8') : undefined;
|
|
119
|
-
const size = contents.byteLength;
|
|
120
|
-
const downloadUrl = encodeURI(
|
|
121
|
-
builder.getDownloadUrlForArtifact(component.id, artifact.task.aspectId, path)
|
|
122
|
-
);
|
|
123
|
-
const externalUrl = vinyl.url;
|
|
124
|
-
return { id: path, name: basename, path, content, downloadUrl, externalUrl, size };
|
|
125
|
-
}
|
|
126
|
-
);
|
|
127
|
-
return {
|
|
128
|
-
id: `${id}-${name}-${artifact.name}`,
|
|
129
|
-
name: artifact.name,
|
|
130
|
-
description: artifact.description,
|
|
131
|
-
task: artifact.task,
|
|
132
|
-
storage: artifact.storage,
|
|
133
|
-
generatedBy: artifact.generatedBy,
|
|
134
|
-
files: artifactFiles,
|
|
135
|
-
};
|
|
136
|
-
} catch (e: any) {
|
|
137
|
-
logger.error(e.toString());
|
|
138
|
-
return {
|
|
139
|
-
id: `${id}-${name}-${artifact.name}`,
|
|
140
|
-
name: artifact.name,
|
|
141
|
-
description: artifact.description,
|
|
142
|
-
task: artifact.task,
|
|
143
|
-
storage: artifact.storage,
|
|
144
|
-
generatedBy: artifact.generatedBy,
|
|
145
|
-
files: [],
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
})
|
|
149
|
-
);
|
|
150
|
-
|
|
151
|
-
const result = pipeline
|
|
152
|
-
.filter((task) => !taskId || task.taskId === taskId)
|
|
153
|
-
.map((task) => ({
|
|
154
|
-
...task,
|
|
155
|
-
id: `filter-${taskId || ''}`,
|
|
156
|
-
artifact: artifactsWithVinyl.find(
|
|
157
|
-
(data) => data.task.aspectId === task.taskId && data.task.name === task.taskName
|
|
158
|
-
),
|
|
159
|
-
}));
|
|
160
|
-
|
|
161
|
-
return result;
|
|
162
|
-
} catch (e: any) {
|
|
163
|
-
logger.error(e.toString());
|
|
164
|
-
return [];
|
|
165
|
-
}
|
|
166
|
-
},
|
|
167
|
-
},
|
|
168
|
-
TaskReport: {
|
|
169
|
-
id: (taskReport: TaskReport & { id?: string }) =>
|
|
170
|
-
`${(taskReport.id && `${taskReport.id}-`) || ''}${taskReport.taskId}-${taskReport.taskName}`,
|
|
171
|
-
description: (taskReport: TaskReport) => taskReport.taskDescription,
|
|
172
|
-
errors: (taskReport: TaskReport) => taskReport.errors?.map((e) => e.toString()) || [],
|
|
173
|
-
warnings: (taskReport: TaskReport) => taskReport.warnings || [],
|
|
174
|
-
artifact: async (taskReport: TaskReport, { path: pathFilter }: { path?: string }) => {
|
|
175
|
-
if (!taskReport.artifact) return undefined;
|
|
176
|
-
return {
|
|
177
|
-
id: `${taskReport.taskId}-${taskReport.taskName}-${taskReport.artifact?.name}-${pathFilter || ''}`,
|
|
178
|
-
...taskReport.artifact,
|
|
179
|
-
files: taskReport.artifact.files.filter((file) => !pathFilter || file.path === pathFilter),
|
|
180
|
-
};
|
|
181
|
-
},
|
|
182
|
-
},
|
|
183
|
-
},
|
|
184
|
-
};
|
|
185
|
-
}
|