diff --git a/src/lib/Components/Workflow/exports/WorkflowJobAbstract.ts b/src/lib/Components/Workflow/exports/WorkflowJobAbstract.ts index 5e1e4de..8b2e1a7 100644 --- a/src/lib/Components/Workflow/exports/WorkflowJobAbstract.ts +++ b/src/lib/Components/Workflow/exports/WorkflowJobAbstract.ts @@ -1,5 +1,7 @@ import { GenerableType } from '../../../Config/exports/Mapping'; +import { AnyCommandShape } from '../../Commands/types/Command.types'; import { Generable } from '../../index'; +import { StepsParameter } from '../../Parameters/types'; import { WorkflowJobContentsShape, WorkflowJobParameters, @@ -24,8 +26,13 @@ export abstract class WorkflowJobAbstract implements Generable { let parameters: WorkflowJobParametersShape | undefined; if (this.parameters) { - const { matrix, ...jobParameters } = this.parameters; - parameters = { ...jobParameters }; + const { matrix, pre_steps, post_steps, ...jobParameters } = + this.parameters; + parameters = { + ...jobParameters, + 'pre-steps': this.generateSteps(pre_steps), + 'post-steps': this.generateSteps(post_steps), + }; if (matrix) { parameters.matrix = { @@ -41,6 +48,10 @@ export abstract class WorkflowJobAbstract implements Generable { return GenerableType.WORKFLOW_JOB; } + private generateSteps(steps?: StepsParameter): AnyCommandShape[] | undefined { + return steps?.map((step) => step.generate()); + } + abstract get name(): string; abstract generate(): WorkflowJobShape; } diff --git a/src/lib/Components/Workflow/types/WorkflowJob.types.ts b/src/lib/Components/Workflow/types/WorkflowJob.types.ts index ffd5598..7e9858c 100644 --- a/src/lib/Components/Workflow/types/WorkflowJob.types.ts +++ b/src/lib/Components/Workflow/types/WorkflowJob.types.ts @@ -2,12 +2,14 @@ import { FilterParameter, ListParameter, MatrixParameter, + StepsParameter, StringParameter, } from '../../Parameters/types'; import { ComponentParameter, JobParameterTypes, } from '../../Parameters/types/ComponentParameters.types'; +import { AnyCommandShape } from '../../Commands/types/Command.types'; /** * CircleCI provided parameters for all workflow jobs @@ -33,6 +35,9 @@ export interface WorkflowJobParameters * An "approval" type job is a special job which pauses the workflow. This "job" is not defined outside of the workflow, you may enter any potential name for the job name. As long as the parameter of "type" is present and equal to "approval" this job will act as a placeholder that awaits user input to continue. */ type?: approval; + + pre_steps?: StepsParameter; + post_steps?: StepsParameter; } export type approval = 'approval'; @@ -57,7 +62,13 @@ export interface WorkflowJobParametersShape { type?: approval; filters?: FilterParameter; matrix?: WorkflowMatrixShape; - [key: string]: JobParameterTypes | WorkflowMatrixShape | undefined; + 'pre-steps'?: AnyCommandShape[]; + 'post-steps'?: AnyCommandShape[]; + [key: string]: + | JobParameterTypes + | WorkflowMatrixShape + | undefined + | AnyCommandShape[]; } /** diff --git a/tests/Workflow.test.ts b/tests/Workflow.test.ts index bff8927..3a7941c 100644 --- a/tests/Workflow.test.ts +++ b/tests/Workflow.test.ts @@ -333,3 +333,34 @@ describe('Add a job to a workflow with a custom name parameter', () => { expect(generatedWorkflow).toEqual(expected); }); }); + +describe('Add pre/post steps to workflow', () => { + const docker = new CircleCI.executors.DockerExecutor('cimg/node:lts'); + const helloWorld = new CircleCI.commands.Run({ + command: 'echo hello world', + }); + const job = new CircleCI.Job('my-job', docker, [helloWorld]); + const myWorkflow = new CircleCI.Workflow('my-workflow'); + myWorkflow.addJob(job, { + name: 'custom-name', + pre_steps: [helloWorld], + post_steps: [helloWorld], + }); + it('Should match the expected output', () => { + const expected = { + 'my-workflow': { + jobs: [ + { + 'my-job': { + name: 'custom-name', + 'post-steps': [{ run: 'echo hello world' }], + 'pre-steps': [{ run: 'echo hello world' }], + }, + }, + ], + }, + }; + const generatedWorkflow = myWorkflow.generate(); + expect(generatedWorkflow).toEqual(expected); + }); +});