Skip to content

Commit

Permalink
feat: added orb import parsing for all config elements
Browse files Browse the repository at this point in the history
  • Loading branch information
Jaryt committed Jul 26, 2022
1 parent e03d3b5 commit a3dda18
Show file tree
Hide file tree
Showing 12 changed files with 172 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,14 @@ export class ReusableCommand implements Command {
*/
generate(): CommandShape {
return {
[this.name]: { ...this.parameters },
[this.name]: this.generateContents(),
};
}

generateContents(): CommandParameters {
return { ...this.parameters };
}

get generableType(): GenerableType {
return GenerableType.REUSABLE_COMMAND;
}
Expand Down
35 changes: 26 additions & 9 deletions src/lib/Components/Commands/parsers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
ParameterizedComponent,
} from '../../../Config/exports/Mapping';
import { errorParsing, parseGenerable } from '../../../Config/exports/Parsing';
import { OrbImport } from '../../../Orb';
import { parseOrbRef } from '../../../Orb/parsers';
import { CustomParametersList } from '../../Parameters';
import { parseParameterList } from '../../Parameters/parsers';
import { CommandParameterLiteral } from '../../Parameters/types/CustomParameterLiterals.types';
Expand Down Expand Up @@ -95,6 +97,7 @@ const nativeSubtypes: CommandSubtypeMap = {
export function parseSteps(
stepsListIn: unknown,
commands?: CustomCommand[],
orbs?: OrbImport[],
): Command[] {
return parseGenerable<
Record<string, unknown>[],
Expand All @@ -108,12 +111,12 @@ export function parseSteps(
return {
steps: stepsListIn.map((subtype) => {
if (typeof subtype === 'string') {
return parseStep(subtype, undefined, commands);
return parseStep(subtype, undefined, commands, orbs);
}

const commandName = Object.keys(subtype)[0];

return parseStep(commandName, subtype[commandName], commands);
return parseStep(commandName, subtype[commandName], commands, orbs);
}),
};
},
Expand All @@ -132,6 +135,7 @@ export function parseStep(
name: string,
args?: unknown,
commands?: CustomCommand[],
orbs?: OrbImport[],
): Command {
if (name in nativeSubtypes) {
const commandMapping = nativeSubtypes[name as NativeCommandLiteral];
Expand All @@ -143,12 +147,18 @@ export function parseStep(
);
}

if (commands) {
if (commands || orbs) {
return parseGenerable<CommandParameters, ReusableCommand>(
GenerableType.REUSABLE_COMMAND,
args,
(parameterArgs) => {
const command = commands.find((c) => c.name === name);
const command =
parseOrbRef<CommandParameterLiteral>(
{ [name]: args },
'commands',
orbs,
) || commands?.find((c) => c.name === name);
console.log(command);

if (!command) {
throw errorParsing(
Expand All @@ -172,13 +182,19 @@ export function parseStep(
* @param custom_commands - The custom commands to parse.
* @returns A list of custom commands.
*/

export function parseCustomCommands(
commandListIn: { [key: string]: unknown },
custom_commands?: CustomCommand[],
orbs?: OrbImport[],
): CustomCommand[] {
return Object.entries(commandListIn).map(([name, args]) =>
parseCustomCommand(name, args, custom_commands),
);
const parsed: CustomCommand[] = [];

Object.entries(commandListIn).forEach(([name, args]) => {
const command = parseCustomCommand(name, args, parsed, orbs);
parsed.push(command);
});

return parsed;
}

/**
Expand All @@ -193,6 +209,7 @@ export function parseCustomCommand(
name: string,
args: unknown,
custom_commands?: CustomCommand[],
orbs?: OrbImport[],
): CustomCommand {
return parseGenerable<
CustomCommandBodyShape,
Expand All @@ -217,7 +234,7 @@ export function parseCustomCommand(
ParameterizedComponent.COMMAND,
) as CustomParametersList<CommandParameterLiteral>);

const steps = parseSteps(commandArgs.steps, custom_commands);
const steps = parseSteps(commandArgs.steps, custom_commands, orbs);

return { parametersList, steps };
},
Expand Down
28 changes: 22 additions & 6 deletions src/lib/Components/Executors/parsers/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { parsers } from '../../../..';
import {
GenerableType,
ParameterizedComponent,
} from '../../../Config/exports/Mapping';
import { errorParsing, parseGenerable } from '../../../Config/exports/Parsing';
import { OrbImport } from '../../../Orb';
import { AnyExecutor } from '../../Job/types/Job.types';
import { CustomParametersList } from '../../Parameters';
import { parseParameterList } from '../../Parameters/parsers';
Expand All @@ -13,6 +15,7 @@ import { Executor } from '../exports/Executor';
import { MachineExecutor } from '../exports/MachineExecutor';
import { MacOSExecutor } from '../exports/MacOSExecutor';
import { ReusableExecutor } from '../exports/ReusableExecutor';
import { ReusedExecutor } from '../exports/ReusedExecutor';
import { WindowsExecutor } from '../exports/WindowsExecutor';
import { DockerResourceClass } from '../types/DockerExecutor.types';
import {
Expand Down Expand Up @@ -82,22 +85,17 @@ const subtypeParsers: ExecutorSubtypeMap = {
// Parses a reusable executor by it's name
executor: {
generableType: GenerableType.REUSED_EXECUTOR,
parse: (args, _, __, reusableExecutors) => {
parse: (args, _, __, reusableExecutors, orbs) => {
const executorArgs = args as
| { name: string; [key: string]: unknown }
| string;

const isFlat = typeof executorArgs === 'string';
const name = isFlat ? executorArgs : executorArgs.name;

const executor = reusableExecutors?.find(
(executor) => executor.name === name,
);

if (!executor) {
throw errorParsing(`Reusable executor ${name} not found in config`);
}

let parameters = undefined;

if (!isFlat) {
Expand All @@ -112,6 +110,22 @@ const subtypeParsers: ExecutorSubtypeMap = {
}
}

if (!executor) {
const orbImport = parsers.parseOrbRef<ExecutorParameterLiteral>(
{ [name]: parameters },
'executors',
orbs,
);

if (!orbImport) {
throw errorParsing(
`Reusable executor ${name} not found in config or any orb`,
);
}

return new ReusedExecutor(orbImport, parameters);
}

return executor.reuse(parameters);
},
},
Expand Down Expand Up @@ -151,6 +165,7 @@ export function extractExecutableProps(
export function parseExecutor(
executableIn: unknown,
reusableExecutors?: ReusableExecutor[],
orbs?: OrbImport[],
): AnyExecutor {
const executableArgs = executableIn as UnknownExecutableShape;
let resourceClass = executableArgs.resource_class;
Expand Down Expand Up @@ -185,6 +200,7 @@ export function parseExecutor(
resourceClass,
extractExecutableProps(executableArgs),
reusableExecutors,
orbs,
);
},
);
Expand Down
2 changes: 2 additions & 0 deletions src/lib/Components/Executors/types/Executor.types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { GenerableType } from '../../../Config/exports/Mapping';
import { OrbImport } from '../../../Orb';
import { AnyExecutor } from '../../Job/types/Job.types';
import { CustomParametersList } from '../../Parameters';
import { ExecutorParameterLiteral } from '../../Parameters/types/CustomParameterLiterals.types';
Expand Down Expand Up @@ -70,4 +71,5 @@ export type ExecutorSubtypeParser = (
resourceClass: AnyResourceClass,
properties?: ExecutableProperties,
reusableExecutors?: ReusableExecutor[],
orbs?: OrbImport[],
) => AnyExecutor;
9 changes: 6 additions & 3 deletions src/lib/Components/Job/parsers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
ParameterizedComponent,
} from '../../../Config/exports/Mapping';
import { parseGenerable } from '../../../Config/exports/Parsing';
import { OrbImport } from '../../../Orb';
import { CustomCommand } from '../../Commands/exports/Reusable/CustomCommand';
import { parseSteps } from '../../Commands/parsers';
import { parseExecutor } from '../../Executors/parsers';
Expand All @@ -27,9 +28,10 @@ export function parseJobList(
jobListIn: { [key: string]: unknown },
customCommands?: CustomCommand[],
reusableExecutors?: ReusableExecutor[],
orbs?: OrbImport[],
): Job[] {
return Object.entries(jobListIn).map(([name, args]) =>
parseJob(name, args, customCommands, reusableExecutors),
parseJob(name, args, customCommands, reusableExecutors, orbs),
);
}

Expand All @@ -49,6 +51,7 @@ export function parseJob(
jobIn: unknown,
customCommands?: CustomCommand[],
reusableExecutors?: ReusableExecutor[],
orbs?: OrbImport[],
): Job {
return parseGenerable<UnknownJobShape, Job, JobDependencies>(
GenerableType.JOB,
Expand All @@ -63,8 +66,8 @@ export function parseJob(
(jobArgs) => {
let parametersList;

const executor = parseExecutor(jobArgs, reusableExecutors);
const steps = parseSteps(jobArgs.steps, customCommands);
const executor = parseExecutor(jobArgs, reusableExecutors, orbs);
const steps = parseSteps(jobArgs.steps, customCommands, orbs);

if (jobArgs.parameters) {
parametersList = parseParameterList(
Expand Down
11 changes: 8 additions & 3 deletions src/lib/Components/Workflow/parsers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,17 @@ export function parseWorkflowJob(
if (args) {
if ('pre-steps' in args) {
const { 'pre-steps': steps, ...argsRestTemp } = args;
parsedPresteps = steps ? parseSteps(steps) : undefined;
parsedPresteps = steps
? parseSteps(steps, undefined, orbs)
: undefined;
args = argsRestTemp;
}

if ('post-steps' in args) {
const { 'post-steps': steps, ...argsRestTemp } = args;
parsedPoststeps = steps ? parseSteps(steps) : undefined;
parsedPoststeps = steps
? parseSteps(steps, undefined, orbs)
: undefined;
args = argsRestTemp;
}
}
Expand Down Expand Up @@ -121,10 +125,11 @@ export function parseWorkflow(
export function parseWorkflowList(
workflowsIn: unknown,
jobs: Job[],
orbs?: OrbImport[],
): Workflow[] {
const workflowList = Object.entries(
workflowsIn as { [name: string]: UnknownWorkflowShape },
).map(([name, workflow]) => parseWorkflow(name, workflow, jobs));
).map(([name, workflow]) => parseWorkflow(name, workflow, jobs, orbs));

return workflowList;
}
2 changes: 2 additions & 0 deletions src/lib/Config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ export class Config
this.commands = commands;
this.parameters = parameters;
this.orbs = orbs;

console.log(orbs);
}

/**
Expand Down
35 changes: 30 additions & 5 deletions src/lib/Config/parsers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { CustomParametersList } from '../../Components/Parameters';
import { parseParameterList } from '../../Components/Parameters/parsers';
import { PipelineParameterLiteral } from '../../Components/Parameters/types/CustomParameterLiterals.types';
import { parseWorkflowList } from '../../Components/Workflow/parsers';
import { parseOrbImports } from '../../Orb/parsers';
import { OrbImportManifest } from '../../Orb/types/Orb.types';
import { GenerableType } from '../exports/Mapping';
import { parseGenerable } from '../exports/Parsing';
import { ConfigDependencies, UnknownConfigShape } from '../types';
Expand All @@ -18,7 +20,10 @@ import { ConfigDependencies, UnknownConfigShape } from '../types';
* @returns A complete config
* @throws Error if any config component not valid
*/
export function parseConfig(configIn: unknown): Config {
export function parseConfig(
configIn: unknown,
orbImportManifests?: Record<string, OrbImportManifest>,
): Config {
const configProps = (
typeof configIn == 'string' ? parse(configIn) : configIn
) as UnknownConfigShape;
Expand All @@ -28,7 +33,14 @@ export function parseConfig(configIn: unknown): Config {
configProps,
(
config,
{ jobList, workflows, executorList, commandList, parameterList },
{
jobList,
workflows,
executorList,
commandList,
parameterList,
orbImportList,
},
) => {
return new Config(
config.setup,
Expand All @@ -37,24 +49,37 @@ export function parseConfig(configIn: unknown): Config {
executorList,
commandList,
parameterList as CustomParametersList<PipelineParameterLiteral>,
orbImportList,
);
},
(config) => {
const orbImportList =
config.orbs && parseOrbImports(config.orbs, orbImportManifests);
const executorList =
config.executors && parseReusableExecutors(config.executors);
const commandList =
config.commands && parseCustomCommands(config.commands);
config.commands && parseCustomCommands(config.commands, orbImportList);
const parameterList =
config.parameters && parseParameterList(config.parameters);
const jobList = parseJobList(config.jobs, commandList, executorList);
const workflows = parseWorkflowList(config.workflows, jobList);
const jobList = parseJobList(
config.jobs,
commandList,
executorList,
orbImportList,
);
const workflows = parseWorkflowList(
config.workflows,
jobList,
orbImportList,
);

return {
jobList,
workflows,
executorList,
commandList,
parameterList,
orbImportList,
};
},
);
Expand Down
2 changes: 2 additions & 0 deletions src/lib/Config/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export type CircleCIConfigShape = {

export type UnknownConfigShape = {
setup: boolean;
orbs?: Record<string, unknown>;
executors?: Record<string, unknown>;
jobs: Record<string, unknown>;
commands?: Record<string, unknown>;
Expand All @@ -60,6 +61,7 @@ export type UnknownConfigShape = {
};

export type ConfigDependencies = {
orbImportList?: OrbImport[];
jobList: Job[];
workflows: Workflow[];
executorList?: ReusableExecutor[];
Expand Down
Loading

0 comments on commit a3dda18

Please sign in to comment.