Skip to content

Commit

Permalink
feat: Parse pre-steps and post-steps for Workflows
Browse files Browse the repository at this point in the history
  • Loading branch information
Jaryt committed Jul 25, 2022
1 parent 48bff2c commit 73883d1
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 33 deletions.
10 changes: 8 additions & 2 deletions src/lib/Components/Workflow/exports/Workflow.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Generable } from '../..';
import { GenerableType } from '../../../Config/exports/Mapping';
import { Command } from '../../Commands/exports/Command';
import { Job } from '../../Job';
import { When } from '../../Logic';
import { Conditional } from '../../Logic/exports/Conditional';
Expand Down Expand Up @@ -68,8 +69,13 @@ export class Workflow implements Generable, Conditional {
/**
* Add a Job to the current Workflow. Chainable
*/
addJob(job: Job, parameters?: WorkflowJobParameters): this {
this.jobs.push(new WorkflowJob(job, parameters));
addJob(
job: Job,
parameters?: WorkflowJobParameters,
pre_steps?: Command[],
post_steps?: Command[],
): this {
this.jobs.push(new WorkflowJob(job, parameters, pre_steps, post_steps));
return this;
}

Expand Down
27 changes: 27 additions & 0 deletions src/lib/Components/Workflow/exports/WorkflowJob.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { OrbRef } from '../../../Orb/exports/OrbRef';
import { AnyCommandShape } from '../../Commands/types/Command.types';
import { Job } from '../../Job';
import { StepsParameter } from '../../Parameters/types';
import { JobParameterLiteral } from '../../Parameters/types/CustomParameterLiterals.types';
import {
WorkflowJobContentsShape,
WorkflowJobParameters,
WorkflowJobShape,
} from '../types/WorkflowJob.types';
Expand All @@ -16,25 +19,49 @@ import { WorkflowJobAbstract } from './WorkflowJobAbstract';
export class WorkflowJob extends WorkflowJobAbstract {
job: Job | OrbRef<JobParameterLiteral>;

pre_steps?: StepsParameter;
post_steps?: StepsParameter;

constructor(
job: Job | OrbRef<JobParameterLiteral>,
parameters?: Exclude<WorkflowJobParameters, 'type'>,
pre_steps?: StepsParameter,
post_steps?: StepsParameter,
) {
super(parameters);
this.job = job;
this.pre_steps = pre_steps;
this.post_steps = post_steps;
}

generate(flatten?: boolean): WorkflowJobShape {
if (this.parameters === undefined) {
return this.job.name;
}

console.log(this.generateContents(flatten));

return {
[this.job.name]: this.generateContents(flatten),
};
}

generateContents(flatten?: boolean): WorkflowJobContentsShape {
return {
...super.generateContents(flatten),
'pre-steps': this.generateSteps(this.pre_steps, flatten),
'post-steps': this.generateSteps(this.post_steps, flatten),
};
}

get name(): string {
return this.job.name;
}

private generateSteps(
steps?: StepsParameter,
flatten?: boolean,
): AnyCommandShape[] | undefined {
return steps?.map((step) => step.generate(flatten));
}
}
19 changes: 3 additions & 16 deletions src/lib/Components/Workflow/exports/WorkflowJobAbstract.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
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,
Expand All @@ -22,17 +20,13 @@ export abstract class WorkflowJobAbstract implements Generable {
this.parameters = parameters;
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
generateContents(flatten?: boolean): WorkflowJobContentsShape {
let parameters: WorkflowJobParametersShape | undefined;

if (this.parameters) {
const { matrix, pre_steps, post_steps, ...jobParameters } =
this.parameters;
parameters = {
...jobParameters,
'pre-steps': this.generateSteps(pre_steps, flatten),
'post-steps': this.generateSteps(post_steps, flatten),
};
const { matrix, ...jobParameters } = this.parameters;
parameters = jobParameters;

if (matrix) {
parameters.matrix = {
Expand All @@ -48,13 +42,6 @@ export abstract class WorkflowJobAbstract implements Generable {
return GenerableType.WORKFLOW_JOB;
}

private generateSteps(
steps?: StepsParameter,
flatten?: boolean,
): AnyCommandShape[] | undefined {
return steps?.map((step) => step.generate(flatten));
}

abstract get name(): string;
abstract generate(flatten?: boolean): WorkflowJobShape;
}
30 changes: 28 additions & 2 deletions src/lib/Components/Workflow/parsers/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { GenerableType } from '../../../Config/exports/Mapping';
import { errorParsing, parseGenerable } from '../../../Config/exports/Parsing';
import { parseSteps } from '../../Commands/parsers';
import { Job } from '../../Job';
import { Workflow } from '../exports/Workflow';
import { WorkflowJob } from '../exports/WorkflowJob';
Expand All @@ -9,6 +10,7 @@ import {
UnknownWorkflowJobShape,
UnknownWorkflowShape,
WorkflowDependencies,
WorkflowJobParameters,
} from '../types';

/**
Expand All @@ -29,14 +31,38 @@ export function parseWorkflowJob(
GenerableType.WORKFLOW_JOB,
workflowJobIn,
(workflowJobArgs) => {
let args = workflowJobArgs;
let parsedPresteps, parsedPoststeps;

if (args) {
if ('pre-steps' in args) {
const { 'pre-steps': steps, ...argsRestTemp } = args;
parsedPresteps = parseSteps(steps);
args = argsRestTemp;
}

if ('post-steps' in args) {
const { 'post-steps': steps, ...argsRestTemp } = args;
parsedPoststeps = parseSteps(steps);
args = argsRestTemp;
}
}

const parameters = args as WorkflowJobParameters | undefined;

if (workflowJobArgs?.type === 'approval') {
return new WorkflowJobApproval(name, workflowJobArgs);
return new WorkflowJobApproval(name, parameters);
}

const job = jobs.find((c) => c.name === name);

if (job) {
return new WorkflowJob(job, workflowJobArgs);
return new WorkflowJob(
job,
parameters,
parsedPresteps,
parsedPoststeps,
);
}

throw errorParsing(`Job ${name} not found in config`);
Expand Down
8 changes: 5 additions & 3 deletions src/lib/Components/Workflow/types/Workflow.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ export type UnknownWorkflowShape = {

export type UnknownWorkflowJobShape = {
requires?: string[];
parameters?: { [key: string]: unknown };
parameters?: {
[key: string]: unknown;
};
'pre-steps'?: unknown[];
'post-steps'?: unknown[];
name?: string;
type?: 'approval';
// 'pre-steps'?: { [key: string]: unknown }[];
// 'post-steps'?: { [key: string]: unknown }[];
};

export type WorkflowDependencies = {
Expand Down
6 changes: 1 addition & 5 deletions src/lib/Components/Workflow/types/WorkflowJob.types.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { AnyCommandShape } from '../../Commands/types/Command.types';
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
Expand All @@ -35,9 +34,6 @@ 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';
Expand Down
17 changes: 12 additions & 5 deletions tests/Workflow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -341,11 +341,14 @@ describe('Add pre/post steps to workflow', () => {
});
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],
});
myWorkflow.addJob(
job,
{
name: 'custom-name',
},
[helloWorld],
[helloWorld],
);
it('Should match the expected output', () => {
const expected = {
'my-workflow': {
Expand All @@ -361,6 +364,10 @@ describe('Add pre/post steps to workflow', () => {
},
};
const generatedWorkflow = myWorkflow.generate(true);

expect(generatedWorkflow).toEqual(expected);
expect(CircleCI.parsers.parseWorkflowList(expected, [job])[0]).toEqual(
myWorkflow,
);
});
});

0 comments on commit 73883d1

Please sign in to comment.