From 7af13a28d53f5f5254bcd6dfd7e1773d18bdbdcb Mon Sep 17 00:00:00 2001 From: snehajais22 Date: Wed, 12 Jun 2024 09:56:53 -0400 Subject: [PATCH 1/3] Clarify id and name properties of builders Signed-off-by: snehajais22 --- src/builders.ts | 67 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 23 deletions(-) diff --git a/src/builders.ts b/src/builders.ts index 15be3d1..6892ac9 100644 --- a/src/builders.ts +++ b/src/builders.ts @@ -84,7 +84,7 @@ export const DefaultBuilderOptions: BuilderOptions = { */ export class WorkspaceBuilder { private readonly _logicalID: string; - private _name?: string; + private _binding?: string; private _description?: string; /** @@ -107,7 +107,7 @@ export class WorkspaceBuilder { * Gets the name of the workspace. */ public get name(): string | undefined { - return this._name; + return this._logicalID; } /** @@ -118,11 +118,18 @@ export class WorkspaceBuilder { } /** - * Sets the name of the workspace. - * @param name + * Gets the binding of task workspace to a pipeline workspace. */ - public withName(name: string): WorkspaceBuilder { - this._name = name; + public get binding(): string | undefined { + return this._binding; + } + + /** + * Sets the binding of a task workspace to a pipeline workspace. + * @param workspace + */ + public withBinding(workspace: string): WorkspaceBuilder { + this._binding = workspace; return this; } @@ -663,14 +670,14 @@ export class TaskBuilder { } /** - * Gets the name of the `Task` built by the `TaskBuilder`. + * Gets the name of the `Task` within a pipeline. */ public get name(): string | undefined { return this._name; } /** - * Sets the name of the `Task` being built. + * Sets the `Task`'s name within a pipeline. * @param name */ public withName(name: string): TaskBuilder { @@ -787,7 +794,7 @@ export class TaskBuilder { const props: TaskProps = { metadata: { - name: this.name, + name: this.logicalID, labels: this._labels, annotations: this._annotations, }, @@ -811,16 +818,26 @@ export class TaskBuilder { export class PipelineBuilder { private readonly _scope: Construct; private readonly _id: string; + /** + * @deprecated pipeline name is given by `id` + */ private _name?: string; private _description?: string; private _tasks?: TaskBuilder[]; + /** + * Creates a new instance of the `PipelineBuilder` using the given `scope` and + * `id`. + * @param scope + * @param id + */ public constructor(scope: Construct, id: string) { this._scope = scope; this._id = id; } /** + * @deprecated pipeline name is set by `id` * Provides the name for the pipeline task and will be * rendered as the `name` property. * @param name @@ -834,7 +851,7 @@ export class PipelineBuilder { * Gets the name of the pipeline */ public get name(): string { - return this._name || this._id; + return this._id; } /** @@ -905,14 +922,18 @@ export class PipelineBuilder { const pipelineWorkspaces = new Map(); this._tasks?.forEach((t) => { t.workspaces?.forEach((w) => { + if (w.binding) { // Only add the workspace on the pipeline level if it is not already // there... - const ws = pipelineWorkspaces.get(w.name!); - if (!ws) { - pipelineWorkspaces.set(w.name!, { - name: w.name, - description: w.description, - }); + const ws = pipelineWorkspaces.get(w.binding); + if (!ws) { + pipelineWorkspaces.set(w.binding, { + name: w.binding, + description: w.description, + }); + } + } else { + throw new Error(`Workspace ${w.logicalID} in Task ${t.name} has no binding to a pipeline workspace.`); } }); }); @@ -947,7 +968,7 @@ export class PipelineBuilder { t.workspaces?.forEach((w) => { taskWorkspaces.push({ name: w.logicalID, - workspace: w.name, + workspace: w.binding, }); }); @@ -960,11 +981,11 @@ export class PipelineBuilder { // built along with the pipeline, but only if we haven't already // built the task yet. if (!taskList.find(it => { - return it == t.name; + return it == t.logicalID; })) { t.buildTask(); } - taskList.push(t.name!); + taskList.push(t.logicalID); } }); @@ -986,9 +1007,9 @@ export class PipelineBuilder { function createOrderedPipelineTask(t: TaskBuilder, after: string, params: TaskParam[], ws: TaskWorkspace[]): PipelineTask { if (after) { return { - name: t.logicalID, + name: t.name || t.logicalID, taskRef: { - name: t.name, + name: t.logicalID, }, runAfter: [after], params: params, @@ -996,9 +1017,9 @@ function createOrderedPipelineTask(t: TaskBuilder, after: string, params: TaskPa }; } return { - name: t.logicalID, + name: t.name || t.logicalID, taskRef: { - name: t.name, + name: t.logicalID, }, params: params, workspaces: ws, From e215411fe5683ac8574933406763cc223d39d0fe Mon Sep 17 00:00:00 2001 From: snehajais22 Date: Wed, 12 Jun 2024 14:15:26 -0400 Subject: [PATCH 2/3] Update builder unit tests Signed-off-by: snehajais22 --- API.md | 49 ++++++++++++--------- src/builders.ts | 21 ++++----- test/pipelinebuilder.test.ts | 82 ++++++++++++++++-------------------- test/taskbuilder.test.ts | 11 ++--- 4 files changed, 79 insertions(+), 84 deletions(-) diff --git a/API.md b/API.md index dbe45ef..b72452d 100644 --- a/API.md +++ b/API.md @@ -2937,8 +2937,8 @@ new PipelineBuilder(scope: Construct, id: string) | **Name** | **Description** | | --- | --- | | buildPipeline | Builds the actual [Pipeline](https://tekton.dev/docs/getting-started/pipelines/) from the settings configured using the fluid syntax. | -| withDescription | Provides the name for the pipeline task and will be rendered as the `name` property. | -| withName | Provides the name for the pipeline task and will be rendered as the `name` property. | +| withDescription | Provides the description for the pipeline. | +| withName | *No description.* | | withStringParam | Add parameter of type string to the Pipeline. | | withTask | *No description.* | @@ -2964,7 +2964,7 @@ Builds the actual [Pipeline](https://tekton.dev/docs/getting-started/pipelines/) public withDescription(description: string): PipelineBuilder ``` -Provides the name for the pipeline task and will be rendered as the `name` property. +Provides the description for the pipeline. ###### `description`Required @@ -2972,14 +2972,12 @@ Provides the name for the pipeline task and will be rendered as the `name` prope --- -##### `withName` +##### ~~`withName`~~ ```typescript public withName(name: string): PipelineBuilder ``` -Provides the name for the pipeline task and will be rendered as the `name` property. - ###### `name`Required - *Type:* string @@ -3326,7 +3324,7 @@ new TaskBuilder(scope: Construct, id: string) | withAnnotation | Adds an annotation to the `Task` `metadata` with the provided key and value. | | withDescription | Sets the `description` of the `Task` being built. | | withLabel | Adds a label to the `Task` with the provided label key and value. | -| withName | Sets the name of the `Task` being built. | +| withName | Sets the name of the `Task` to be used within a pipeline. | | withResult | Allows you to add a result to the Task. | | withStep | Adds the given `step` (`TaskStepBuilder`) to the `Task`. | | withStringParam | Adds a parameter of type string to the `Task`. | @@ -3410,7 +3408,7 @@ Adds a label to the `Task` with the provided label key and value. public withName(name: string): TaskBuilder ``` -Sets the name of the `Task` being built. +Sets the name of the `Task` to be used within a pipeline. ###### `name`Required @@ -3493,7 +3491,7 @@ Adds the specified workspace to the `Task`. | --- | --- | --- | | logicalID | string | *No description.* | | description | string | Gets the `description` of the `Task`. | -| name | string | Gets the name of the `Task` built by the `TaskBuilder`. | +| name | string | Gets the name of the `Task` in the context of a pipeline. | | parameters | ParameterBuilder[] | *No description.* | | workspaces | WorkspaceBuilder[] | Gets the workspaces for the `Task`. | @@ -3529,7 +3527,7 @@ public readonly name: string; - *Type:* string -Gets the name of the `Task` built by the `TaskBuilder`. +Gets the name of the `Task` in the context of a pipeline. --- @@ -3951,34 +3949,34 @@ new WorkspaceBuilder(id: string) | **Name** | **Description** | | --- | --- | +| withBinding | Sets the binding of a task workspace to a pipeline workspace. | | withDescription | Sets the description of the workspace. | -| withName | Sets the name of the workspace. | --- -##### `withDescription` +##### `withBinding` ```typescript -public withDescription(desc: string): WorkspaceBuilder +public withBinding(workspace: string): WorkspaceBuilder ``` -Sets the description of the workspace. +Sets the binding of a task workspace to a pipeline workspace. -###### `desc`Required +###### `workspace`Required - *Type:* string --- -##### `withName` +##### `withDescription` ```typescript -public withName(name: string): WorkspaceBuilder +public withDescription(desc: string): WorkspaceBuilder ``` -Sets the name of the workspace. +Sets the description of the workspace. -###### `name`Required +###### `desc`Required - *Type:* string @@ -3990,6 +3988,7 @@ Sets the name of the workspace. | **Name** | **Type** | **Description** | | --- | --- | --- | | description | string | Gets the description of the workspace. | +| binding | string | Gets the binding of task workspace to a pipeline workspace. | | logicalID | string | Gets the logical ID of the `Workspace`. | | name | string | Gets the name of the workspace. | @@ -4007,6 +4006,18 @@ Gets the description of the workspace. --- +##### `binding`Optional + +```typescript +public readonly binding: string; +``` + +- *Type:* string + +Gets the binding of task workspace to a pipeline workspace. + +--- + ##### `logicalID`Optional ```typescript diff --git a/src/builders.ts b/src/builders.ts index 5400c5c..e57f663 100644 --- a/src/builders.ts +++ b/src/builders.ts @@ -716,14 +716,14 @@ export class TaskBuilder { } /** - * Gets the name of the `Task` within a pipeline. + * Gets the name of the `Task` in the context of a pipeline. */ public get name(): string | undefined { return this._name; } /** - * Sets the `Task`'s name within a pipeline. + * Sets the name of the `Task` to be used within a pipeline. * @param name */ public withName(name: string): TaskBuilder { @@ -864,23 +864,21 @@ export class TaskBuilder { export class PipelineBuilder { private readonly _scope: Construct; private readonly _id: string; - /** - * @deprecated pipeline name is given by `id` - */ - private _name?: string; + private _name: string; private _description?: string; private _tasks?: TaskBuilder[]; private _params?: Map; /** * Creates a new instance of the `PipelineBuilder` using the given `scope` and - * `id`. + * `id`. `id` also sets the pipeline's name. * @param scope * @param id */ public constructor(scope: Construct, id: string) { this._scope = scope; this._id = id; + this._name = id; } /** @@ -898,12 +896,11 @@ export class PipelineBuilder { * Gets the name of the pipeline */ public get name(): string { - return this._id; + return this._name; } /** - * Provides the name for the pipeline task and will be - * rendered as the `name` property. + * Provides the description for the pipeline. * @param description */ public withDescription(description: string): PipelineBuilder { @@ -998,7 +995,7 @@ export class PipelineBuilder { }); } } else { - throw new Error(`Workspace ${w.logicalID} in Task ${t.name} has no binding to a pipeline workspace.`); + throw new Error(`Workspace '${w.logicalID}' in Task '${t.name}' has no binding to a workspace in Pipeline '${this.name}'.`); } }); }); @@ -1037,7 +1034,7 @@ export class PipelineBuilder { }); }); - const pt = createOrderedPipelineTask(t, ((i > 0) ? this._tasks![i - 1].logicalID : ''), taskParams, taskWorkspaces); + const pt = createOrderedPipelineTask(t, ((i > 0) ? (this._tasks![i - 1].name || this._tasks![i - 1].logicalID) : ''), taskParams, taskWorkspaces); pipelineTasks.push(pt); diff --git a/test/pipelinebuilder.test.ts b/test/pipelinebuilder.test.ts index ececfc0..65efef5 100644 --- a/test/pipelinebuilder.test.ts +++ b/test/pipelinebuilder.test.ts @@ -19,15 +19,14 @@ class PipelineRunTest extends Chart { const pipelineParam = new ParameterBuilder('repo-url') .withDefaultValue(''); - const myTask = new TaskBuilder(this, 'fetch-source') - .withName('git-clone') + const myTask = new TaskBuilder(this, 'git-clone') + .withName('fetch-source') .withWorkspace(new WorkspaceBuilder('output') - .withName('shared-data') + .withBinding('shared-data') .withDescription('The files cloned by the task')) .withStringParam(new ParameterBuilder('url').withValue(fromPipelineParam(pipelineParam))); - const pipeline = new PipelineBuilder(this, 'my-pipeline') - .withName('clone-build-push') + const pipeline = new PipelineBuilder(this, 'clone-build-push') .withDescription('This pipeline closes a repository, builds a Docker image, etc.') .withTask(myTask) .withStringParam(pipelineParam); @@ -47,15 +46,14 @@ class PipelineRunTestWithUndefinedWorkspaceError extends Chart { const pipelineParam = new ParameterBuilder('repo-url') .withDefaultValue(''); - const myTask = new TaskBuilder(this, 'fetch-source') - .withName('git-clone') + const myTask = new TaskBuilder(this, 'git-clone') + .withName('fetch-source') .withWorkspace(new WorkspaceBuilder('output') - .withName('shared-data') + .withBinding('shared-data') .withDescription('The files cloned by the task')) .withStringParam(new ParameterBuilder('url').withValue(fromPipelineParam(pipelineParam))); - const pipeline = new PipelineBuilder(this, 'my-pipeline') - .withName('clone-build-push') + const pipeline = new PipelineBuilder(this, 'clone-build-push') .withDescription('This pipeline closes a repository, builds a Docker image, etc.') .withTask(myTask) .withStringParam(pipelineParam); @@ -74,15 +72,14 @@ class PipelineRunTestWithUndefinedParamError extends Chart { const pipelineParam = new ParameterBuilder('repo-url') .withDefaultValue(''); - const myTask = new TaskBuilder(this, 'fetch-source') - .withName('git-clone') + const myTask = new TaskBuilder(this, 'git-clone') + .withName('fetch-source') .withWorkspace(new WorkspaceBuilder('output') - .withName('shared-data') + .withBinding('shared-data') .withDescription('The files cloned by the task')) .withStringParam(new ParameterBuilder('url').withValue(fromPipelineParam(pipelineParam))); - const pipeline = new PipelineBuilder(this, 'my-pipeline') - .withName('clone-build-push') + const pipeline = new PipelineBuilder(this, 'clone-build-push') .withDescription('This pipeline closes a repository, builds a Docker image, etc.') .withTask(myTask) .withStringParam(pipelineParam); @@ -102,15 +99,14 @@ class PipelineRunTestWithError extends Chart { const pipelineParam = new ParameterBuilder('repo-url') .withDefaultValue(''); - const myTask = new TaskBuilder(this, 'fetch-source') - .withName('git-clone') + const myTask = new TaskBuilder(this, 'git-clone') + .withName('fetch-source') .withWorkspace(new WorkspaceBuilder('output') - .withName('shared-data') + .withBinding('shared-data') .withDescription('The files cloned by the task')) .withStringParam(new ParameterBuilder('url').withValue(fromPipelineParam(pipelineParam))); - const pipeline = new PipelineBuilder(this, 'my-pipeline') - .withName('clone-build-push') + const pipeline = new PipelineBuilder(this, 'clone-build-push') .withDescription('This pipeline closes a repository, builds a Docker image, etc.') .withTask(myTask) .withStringParam(pipelineParam); @@ -136,24 +132,23 @@ class MySecondTestChart extends Chart { const questParam = new ParameterBuilder('your-quest') .withDefaultValue(''); - const myTask = new TaskBuilder(this, 'git-clone') - .withName('fetch-source') + const myTask = new TaskBuilder(this, 'fetch-source') + .withName('git-clone') .withWorkspace(new WorkspaceBuilder('output') - .withName('shared-data') + .withBinding('shared-data') .withDescription('The files cloned by the task')) .withWorkspace(new WorkspaceBuilder('ssh-credentials') - .withName('ssh-creds') + .withBinding('ssh-creds') .withDescription('The SSH files for credentials')) .withWorkspace(new WorkspaceBuilder('config') - .withName('config-data') + .withBinding('config-data') .withDescription('The files for configuration for stuff')) .withStringParam(new ParameterBuilder('url').withValue(fromPipelineParam(repoParam))) .withStringParam(new ParameterBuilder('name').withValue(fromPipelineParam(nameParam))) .withStringParam(new ParameterBuilder('color').withValue(fromPipelineParam(colorParam))) .withStringParam(new ParameterBuilder('quest').withValue(fromPipelineParam(questParam))); - new PipelineBuilder(this, 'my-test-pipeline-2') - .withName('clone-build-push') + new PipelineBuilder(this, 'clone-build-push') .withDescription('This pipeline closes a repository, builds a Docker image, etc.') .withTask(myTask) .withStringParam(repoParam) @@ -170,7 +165,7 @@ class MyTestChartWithDuplicateParams extends Chart { const myWorkspace = new WorkspaceBuilder('output') .withDescription('The files cloned by the task') - .withName('shared-data'); + .withBinding('shared-data'); const pipelineParam = new ParameterBuilder('repo-url') .withDefaultValue(''); @@ -178,20 +173,19 @@ class MyTestChartWithDuplicateParams extends Chart { const urlParam = new ParameterBuilder('url') .withValue(fromPipelineParam(pipelineParam)); - const myTask = new TaskBuilder(this, 'git-clone') - .withName('fetch-source') + const myTask = new TaskBuilder(this, 'fetch-source') + .withName('git-clone') .withWorkspace(myWorkspace) .withStringParam(urlParam) ; - const myTask2 = new TaskBuilder(this, 'cat-readme') - .withName('print-readme') + const myTask2 = new TaskBuilder(this, 'print-readme') + .withName('cat-readme') .withWorkspace(myWorkspace) .withStringParam(urlParam) ; - new PipelineBuilder(this, 'my-pipeline') - .withName('clone-build-push') + new PipelineBuilder(this, 'clone-build-push') .withDescription('This pipeline closes a repository, builds a Docker image, etc.') .withTask(myTask) .withTask(myTask2) @@ -211,16 +205,15 @@ class MyTestChartWithStaticOverride extends Chart { const urlParam = new ParameterBuilder('url') .withValue(fromPipelineParam(pipelineParam)); - const myTask2 = new TaskBuilder(this, 'cat-readme') - .withName('print-readme') + const myTask2 = new TaskBuilder(this, 'print-readme') + .withName('cat-readme') .withStringParam(urlParam) ; // This should override the parameter with a static value. myTask2.withStringParam(new ParameterBuilder('url').withValue('https://api.example.io')); - new PipelineBuilder(this, 'my-pipeline') - .withName('clone-build-push') + new PipelineBuilder(this, 'clone-build-push') .withDescription('This pipeline closes a repository, builds a Docker image, etc.') .withTask(myTask2) // pipelineParam not added because myTask2 doesn't reference it anymore @@ -234,7 +227,7 @@ class MyTestChartWithDuplicateTasks extends Chart { const myWorkspace = new WorkspaceBuilder('output') .withDescription('The files cloned by the task') - .withName('shared-data'); + .withBinding('shared-data'); const pipelineParam = new ParameterBuilder('repo-url') .withDefaultValue(''); @@ -242,14 +235,13 @@ class MyTestChartWithDuplicateTasks extends Chart { const urlParam = new ParameterBuilder('url') .withValue(fromPipelineParam(pipelineParam)); - const myTask = new TaskBuilder(this, 'git-clone') - .withName('fetch-source') + const myTask = new TaskBuilder(this, 'fetch-source') + .withName('git-clone') .withWorkspace(myWorkspace) .withStringParam(urlParam) ; - new PipelineBuilder(this, 'my-pipeline') - .withName('clone-build-push') + new PipelineBuilder(this, 'clone-build-push') .withDescription('This pipeline closes a repository, builds a Docker image, etc.') .withTask(myTask) .withTask(myTask) @@ -271,8 +263,8 @@ class PipelineLevelParamTest extends Chart { const taskParam2 = new ParameterBuilder('pathToContext') .withValue(fromPipelineParam(pipelineParam)); - const myTask = new TaskBuilder(this, 'build-skaffold-web') - .withName('build-push') + const myTask = new TaskBuilder(this, 'build-push') + .withName('build-skaffold-web') .withStringParam(taskParam) .withStringParam(taskParam2); diff --git a/test/taskbuilder.test.ts b/test/taskbuilder.test.ts index b4eec97..92fd580 100644 --- a/test/taskbuilder.test.ts +++ b/test/taskbuilder.test.ts @@ -23,8 +23,7 @@ class TestBasicTaskBuild extends Chart { .ofType('string') .withValue(fromPipelineParam(pipelineParam)); - new TaskBuilder(this, 'my-task') - .withName('ansible-runner') + new TaskBuilder(this, 'ansible-runner') .withDescription('Task to run Ansible playbooks using Ansible Runner') .withWorkspace(runnerDir) .withStringParam(projectDirName) @@ -87,8 +86,7 @@ class TestBasicTaskBuildFromObject extends Chart { .ofType('string') .withValue(fromPipelineParam(pipelineParam)); - new TaskBuilder(this, 'my-task') - .withName('ansible-runner') + new TaskBuilder(this, 'ansible-runner') .withDescription('Task to run Ansible playbooks using Ansible Runner') .withWorkspace(runnerDir) .withStringParam(projectDirName) @@ -109,8 +107,7 @@ class TestBasicTaskBuildFromScriptData extends Chart { constructor(scope: Construct, id: string, props?: ChartProps) { super(scope, id, props); - new TaskBuilder(this, 'my-task') - .withName('ansible-runner') + new TaskBuilder(this, 'ansible-runner') .withDescription('Task to run Ansible playbooks using Ansible Runner') .withStep(new TaskStepBuilder() .withName('requirements') @@ -129,7 +126,6 @@ class TestIBMCloudSecretsManagerGet extends Chart { super(scope, id, props); new TaskBuilder(this, 'ibmcloud-secrets-manager-get') - .withName('ibmcloud-secrets-manager-get') .withLabel('app.kubernetes.io/version', '0.1') .withAnnotation('tekton.dev/categories', 'IBM Cloud') .withAnnotation('tekton.dev/pipelines.minVersion', '0.17.0') @@ -160,7 +156,6 @@ class TestPullRequestTaskBuild extends Chart { // be nice to compare the snapshots with each other just to make sure that the // builder does build the exact same object as the longer, non-builder method. new TaskBuilder(this, 'pull-request') - .withName('pull-request') .withDescription('This Task allows a user to interact with an SCM (source control management)\nsystem through an abstracted interface\n\nThis Task works with both public SCM instances and self-hosted/enterprise GitHub/GitLab\ninstances. In download mode, this Task will look at the state of an existing pull\nrequest and populate the pr workspace with the state of the pull request, including the\n.MANIFEST file. In upload mode, this Task will look at the contents of the pr workspace\n and compare it to the .MANIFEST file (if it exists).') .withStringParam(new ParameterBuilder('mode') .withValue(fromPipelineParam(new ParameterBuilder('mode'))) From e1e133d7c8c68d11337a4f199a3c0a142aba63f2 Mon Sep 17 00:00:00 2001 From: snehajais22 Date: Fri, 14 Jun 2024 10:12:13 -0400 Subject: [PATCH 3/3] Check task names are unique in pipeline, with updated tests Signed-off-by: snehajais22 --- src/builders.ts | 10 + .../pipelinebuilder.test.ts.snap | 182 +++++++++--------- test/pipelinebuilder.test.ts | 52 ++++- 3 files changed, 148 insertions(+), 96 deletions(-) diff --git a/src/builders.ts b/src/builders.ts index e57f663..b8b9121 100644 --- a/src/builders.ts +++ b/src/builders.ts @@ -1014,9 +1014,19 @@ export class PipelineBuilder { // the build. Not that it really hurts anything, but it makes the multidoc // YAML file bigger and more complex than it needs to be. const taskList: string[] = new Array(); + // To ensure that all tasks in the pipeline have unique names. + const taskNames: string[] = new Array(); this._tasks?.forEach((t, i) => { + const taskName = t.name || t.logicalID; + if (taskNames.find(it => { + return it == taskName; + })) { + throw new Error(`Multiple tasks found with name '${taskName}' in Pipeline '${this.name}', but task names must be unique.`); + } + taskNames.push(taskName); + const taskParams: TaskParam[] = new Array(); const taskWorkspaces: PipelineTaskWorkspace[] = new Array(); diff --git a/test/__snapshots__/pipelinebuilder.test.ts.snap b/test/__snapshots__/pipelinebuilder.test.ts.snap index 92bfede..8e60bbe 100644 --- a/test/__snapshots__/pipelinebuilder.test.ts.snap +++ b/test/__snapshots__/pipelinebuilder.test.ts.snap @@ -91,35 +91,8 @@ exports[`PipelineBuilderTest PipelineBuilderWithComplexTasks 1`] = ` ] `; -exports[`PipelineBuilderTest PipelineBuilderWithDuplicateTasks 1`] = ` +exports[`PipelineBuilderTest PipelineBuilderWithDuplicates 1`] = ` [ - { - "apiVersion": "tekton.dev/v1", - "kind": "Task", - "metadata": { - "annotations": undefined, - "labels": undefined, - "name": "fetch-source", - }, - "spec": { - "description": undefined, - "params": [ - { - "default": "", - "description": "", - "name": "url", - }, - ], - "results": [], - "steps": [], - "workspaces": [ - { - "description": "The files cloned by the task", - "name": "output", - }, - ], - }, - }, { "apiVersion": "tekton.dev/v1", "kind": "Pipeline", @@ -155,7 +128,7 @@ exports[`PipelineBuilderTest PipelineBuilderWithDuplicateTasks 1`] = ` ], }, { - "name": "git-clone", + "name": "cat-readme", "params": [ { "name": "url", @@ -166,7 +139,7 @@ exports[`PipelineBuilderTest PipelineBuilderWithDuplicateTasks 1`] = ` "git-clone", ], "taskRef": { - "name": "fetch-source", + "name": "print-readme", }, "workspaces": [ { @@ -187,76 +160,76 @@ exports[`PipelineBuilderTest PipelineBuilderWithDuplicateTasks 1`] = ` ] `; -exports[`PipelineBuilderTest PipelineBuilderWithDuplicates 1`] = ` +exports[`PipelineBuilderTest PipelineBuilderWithParameters 1`] = ` [ { "apiVersion": "tekton.dev/v1", - "kind": "Pipeline", + "kind": "Task", "metadata": { - "name": "clone-build-push", + "annotations": undefined, + "labels": undefined, + "name": "build-push", }, "spec": { - "description": "This pipeline closes a repository, builds a Docker image, etc.", + "description": undefined, "params": [ { "default": "", - "name": "repo-url", + "description": "", + "name": "pathToDockerFile", + }, + { + "default": "", + "description": "", + "name": "pathToContext", + }, + ], + "results": [], + "steps": [], + "workspaces": [], + }, + }, + { + "apiVersion": "tekton.dev/v1", + "kind": "Pipeline", + "metadata": { + "name": "pipeline-with-parameters", + }, + "spec": { + "description": undefined, + "params": [ + { + "default": "/some/where/or/other", + "name": "context", "type": "string", }, ], "tasks": [ { - "name": "git-clone", + "name": "build-skaffold-web", "params": [ { - "name": "url", - "value": "$(params.repo-url)", - }, - ], - "taskRef": { - "name": "fetch-source", - }, - "workspaces": [ - { - "name": "output", - "workspace": "shared-data", + "name": "pathToDockerFile", + "value": "Dockerfile", }, - ], - }, - { - "name": "cat-readme", - "params": [ { - "name": "url", - "value": "$(params.repo-url)", + "name": "pathToContext", + "value": "$(params.context)", }, ], - "runAfter": [ - "git-clone", - ], "taskRef": { - "name": "print-readme", + "name": "build-push", }, - "workspaces": [ - { - "name": "output", - "workspace": "shared-data", - }, - ], - }, - ], - "workspaces": [ - { - "description": "The files cloned by the task", - "name": "shared-data", + "workspaces": [], }, ], + "workspaces": [], }, }, ] `; -exports[`PipelineBuilderTest PipelineBuilderWithParameters 1`] = ` +exports[`PipelineBuilderTest PipelineBuilderWithSimilarTasks 1`] = ` [ { "apiVersion": "tekton.dev/v1", @@ -264,7 +237,7 @@ exports[`PipelineBuilderTest PipelineBuilderWithParameters 1`] = ` "metadata": { "annotations": undefined, "labels": undefined, - "name": "build-push", + "name": "fetch-source", }, "spec": { "description": undefined, @@ -272,54 +245,81 @@ exports[`PipelineBuilderTest PipelineBuilderWithParameters 1`] = ` { "default": "", "description": "", - "name": "pathToDockerFile", - }, - { - "default": "", - "description": "", - "name": "pathToContext", + "name": "url", }, ], "results": [], "steps": [], - "workspaces": [], + "workspaces": [ + { + "description": "The files cloned by the task", + "name": "output", + }, + ], }, }, { "apiVersion": "tekton.dev/v1", "kind": "Pipeline", "metadata": { - "name": "pipeline-with-parameters", + "name": "clone-build-push", }, "spec": { - "description": undefined, + "description": "This pipeline closes a repository, builds a Docker image, etc.", "params": [ { - "default": "/some/where/or/other", - "name": "context", + "default": "", + "name": "repo-url", "type": "string", }, ], "tasks": [ { - "name": "build-skaffold-web", + "name": "git-clone", "params": [ { - "name": "pathToDockerFile", - "value": "Dockerfile", + "name": "url", + "value": "$(params.repo-url)", }, + ], + "taskRef": { + "name": "fetch-source", + }, + "workspaces": [ { - "name": "pathToContext", - "value": "$(params.context)", + "name": "output", + "workspace": "shared-data", + }, + ], + }, + { + "name": "git-clone-2", + "params": [ + { + "name": "url", + "value": "$(params.repo-url)", }, ], + "runAfter": [ + "git-clone", + ], "taskRef": { - "name": "build-push", + "name": "fetch-source", }, - "workspaces": [], + "workspaces": [ + { + "name": "output", + "workspace": "shared-data", + }, + ], + }, + ], + "workspaces": [ + { + "description": "The files cloned by the task", + "name": "shared-data", }, ], - "workspaces": [], }, }, ] diff --git a/test/pipelinebuilder.test.ts b/test/pipelinebuilder.test.ts index 65efef5..55618e3 100644 --- a/test/pipelinebuilder.test.ts +++ b/test/pipelinebuilder.test.ts @@ -221,7 +221,7 @@ class MyTestChartWithStaticOverride extends Chart { } } -class MyTestChartWithDuplicateTasks extends Chart { +class MyTestChartWithDuplicateTasksError extends Chart { constructor(scope: Construct, id: string, props?: ChartProps) { super(scope, id, props); @@ -275,6 +275,40 @@ class PipelineLevelParamTest extends Chart { } } +class MyTestChartWithSimilarTasks extends Chart { + constructor(scope: Construct, id: string, props?: ChartProps) { + super(scope, id, props); + + const myWorkspace = new WorkspaceBuilder('output') + .withDescription('The files cloned by the task') + .withBinding('shared-data'); + + const pipelineParam = new ParameterBuilder('repo-url') + .withDefaultValue(''); + + const urlParam = new ParameterBuilder('url') + .withValue(fromPipelineParam(pipelineParam)); + + const myTask = new TaskBuilder(this, 'fetch-source') + .withName('git-clone') + .withWorkspace(myWorkspace) + .withStringParam(urlParam) + ; + + const myTask2 = new TaskBuilder(this, 'fetch-source') + .withName('git-clone-2') + .withWorkspace(myWorkspace) + .withStringParam(urlParam); + + new PipelineBuilder(this, 'clone-build-push') + .withDescription('This pipeline closes a repository, builds a Docker image, etc.') + .withTask(myTask) + .withTask(myTask2) + .withStringParam(pipelineParam) + .buildPipeline({ includeDependencies: true }); + } +} + describe('PipelineBuilderTest', () => { test('PipelineRunBuilder', () => { const app = Testing.app(); @@ -328,11 +362,12 @@ describe('PipelineBuilderTest', () => { expect(results).toMatchSnapshot(); }); - test('PipelineBuilderWithDuplicateTasks', () => { + test('PipelineBuilderWithDuplicateTasksError', () => { const app = Testing.app(); - const chart = new MyTestChartWithDuplicateTasks(app, 'test-chart'); - const results = Testing.synth(chart); - expect(results).toMatchSnapshot(); + const f = () => { + new MyTestChartWithDuplicateTasksError(app, 'test-chart'); + }; + expect(f).toThrowError('Multiple tasks found with name \'git-clone\' in Pipeline \'clone-build-push\', but task names must be unique.'); }); test('PipelineBuilderWithParameters', () => { @@ -341,4 +376,11 @@ describe('PipelineBuilderTest', () => { const results = Testing.synth(chart); expect(results).toMatchSnapshot(); }); + + test('PipelineBuilderWithSimilarTasks', () => { + const app = Testing.app(); + const chart = new MyTestChartWithSimilarTasks(app, 'test-chart'); + const results = Testing.synth(chart); + expect(results).toMatchSnapshot(); + }); });