Build tasks are component development operations that are executed in sequence, in one or more build pipelines (build pipeline, snap pipeline, or tag pipeline).
The easiest way to start implementing a Build Task is by using the 'build-task' template:
bit create build-task modules/my-task
Fork a complete example
Fork an example build task component and edit it in your workspace:
bit fork teambit.pipelines/examples/modules/loc-stats
To identify your build task in various outputs and logs, set task name (name). Since there may be various Aspects that may register the build task, we allow for instantiating it with an Aspect ID (aspectId) of the aspect that registered the task.
export class MyTask implements BuildTask { constructor(readonly aspectId: string) {} readonly name = 'MyBuildTask'; }
The build task receives the Build context (context) from the Builder aspect. The context provides data on all generated capsules in this instance of the build process.
Build tasks run on components, grouped by their Envs. This means that depending on the env, you will get different instance of capsules. For example, when the task runs over teambit.react/react Env's components, the capsules will only be for components that have the teambit.react/react Env configured.
Iterate over each capsule and run any operation for the component in the capsule.
async execute(context: BuildContext): Promise<BuiltTaskResult> { const capsules = context.capsuleNetwork.seedersCapsules; capsules.forEach((capsule) => { console.log(`This component's name is: ${capsule.component.id.name}`); } return { // ... } }
About seeder capsules
In most cases, the Capsules you should care about are the 'Seeder Capsules' (seedersCapsules). These are the Capsules that are intentionally being built (others are for the dependent-components).
Build tasks must return data about the components they processed (componentsResults). This may be used for errors, start and end timestamps, etc.
When tasks are executed as part of the snap or tag processes, Bit persists the data as part of the snapshot.
async execute(context: BuildContext): Promise<BuiltTaskResult> { // ... const componentsResults: ComponentResult[]; const capsules = context.capsuleNetwork.seedersCapsules; capsules.forEach((capsule) => { componentsResults.push(capsule.component) } return { componentsResults, }; }
The artifacts your build task generates can be persisted in the component version. Select the relevant artifacts using a glob pattern, and set a description for them (non-selected artifacts will not be persisted).
A single task may return more than a single set of artifacts. In that case, the name (name) given for them should distinguish one set of artifacts from another (for example, a single compilation task that generates code transpiled to 'ES2015' and 'ES2020' standards)
async execute(context: BuildContext): Promise<BuiltTaskResult> { // ... return { artifacts: [ { generatedBy: this.aspectId, name: `component snapshots`, globPatterns: [`snapshots/**`], }, ], componentsResults, }; }
aspectId
aspectId: string;
The component ID of the environment using this task.
name
name: string;
A name for this task. Only alphanumerical characters are allowed. PascalCase should be used as a convention.
location
location?: 'start' | 'end'
The section of the build-pipeline to which to append this task.
dependencies
dependencies?: string[]
An list of tasks that must be completed before this task gets executed.
For example dependencies = ['@teambit/preview'].
execute
execute(context: BuildContext): Promise<BuiltTaskResult>
The execute method is where all the task logic is placed.
context
context: BuildContext;
The context of the build pipeline. Use this object (provided by Builder) to get information regarding all components handled by the build pipeline.
For example, context.capsuleNetwork.seedersCapsules are models representing isolated instances of components handled by the build pipeline. These isolated instances are independent projects, generated in your local filesystem (by the build pipeline).
Learn more about BuildContext here.
return (BuiltTaskResult)
Promise<BuiltTaskResult>
Returns an object with data regarding the build task process, additional data regarding the components handled by the task and, if available, data regarding the different artifacts generated by this task.
The returned object BuiltTaskResult has the following attributes:
componentsResults
componentsResults: ComponentResult[]An array of objects, each containing an instance of an object handled the task and additional information regarding the process and the component itself.component
component: Component
An instance of the component handled by the task (see the above task example).metadata
metadata?: { [key: string]: Serializable }
Component metadata generated during the build task.errors
errors?: Array<Error | string>
Build task errors. A task returning errors will abort the build pipeline and log the returned errors.warnings
warnings?: string[]
warnings generated throughout the build task.startTime
startTime?: number
A timestamp (in milliseconds) of when the task startedendTime
endTime?: number
A timestamp (in milliseconds) of when the task endedartifacts
artifacts?: ArtifactDefinition[]
Use this to provide the builder with artifacts to persist in the component version (component objects).
For example:[{ name: 'my-img-artifacts' globPatterns: 'generated_images/*.jpg' }, ]; }]Learn more about Artifact Definition here.
name
name: string
The name of the artifact.
For example, a project might utilize two different artifacts for the same typescript compiler, one that generates ES5 files and another for ES6. This prop helps to distinguish between the two.generatedBy
generatedBy?: string;
Id of the component that generated this artifact.description
description?: string
A description of the artifact.globPatterns
globPatterns: string[]
Glob patterns of files to include upon artifact creation. Minimatch is used to match the patterns.
For example,['*.ts', '!foo.ts']matches all ts files but ignoresfoo.ts.rootDir
rootDir?: string
Defines the root directory of the artifacts in the capsule file system. The rootDir must be unique for every artifact, otherwise data might be overridden.dirPrefix
dirPrefix?: string
Adds a directory prefix for all artifact files.context
context?: 'component' | 'env'
Determine the context of the artifact. The default artifact context iscomponent.envis useful when the same file is generated for all components, for example, a "preview" task may create the same webpack file for all components of that env.storageResolver
storageResolver?: string
Used to replace the location of the stored artifacts. The default resolver persists artifacts on scope (that's not recommended for large files).preBuild
preBuild?(context: BuildContext): Promise<void>
Runs before the build pipeline has started. This method should only be used when preparations are needed to be done on all environments before the build starts.postBuild
postBuild?(context: BuildContext, tasksResults: TaskResultsList): Promise<void>
Runs after the dependencies were completed for all environments.
BuildContext
components
components: Component[]
All components about to be built/tagged.
capsuleNetwork
capsuleNetwork: Network;
The network of capsules ready to be built. This includes:
'Seeders': Components that where explicitly built (e.g,
bit build <components>).'Graph capsules' Seeders and their dependencies (dependencies that are also handled by the workspace)
Learn more about Network here.
seedersCapsules
seedersCapsules: CapsuleList;
The seeders' capsules.
graphCapsules
graphCapsules: CapsuleList;
All capsules, including the dependencies of the seeders (even when they belong to another env).
capsulesRootDir
capsulesRootDir: string;
The absolute path to the capsules' root directory.