chore: added validation for schemas for actions

Signed-off-by: blam <ben@blam.sh>

Signed-off-by: blam <ben@blam.sh>
This commit is contained in:
blam
2021-09-28 04:29:19 +02:00
parent c7b089a5ae
commit fe2324e630
2 changed files with 68 additions and 2 deletions
@@ -55,6 +55,23 @@ describe('DefaultWorkflowRunner', () => {
handler: fakeActionHandler,
});
actionRegistry.register({
id: 'jest-validated-action',
description: 'Mock action for testing',
handler: fakeActionHandler,
schema: {
input: {
type: 'object',
required: ['foo'],
properties: {
foo: {
type: 'number',
},
},
},
},
});
actionRegistry.register({
id: 'output-action',
description: 'Mock action for testing',
@@ -85,7 +102,40 @@ describe('DefaultWorkflowRunner', () => {
);
});
describe('validation', () => {});
describe('validation', () => {
it('should throw an error if the action has a schema and the input does not match', async () => {
const task = createMockTaskWithSpec({
apiVersion: 'backstage.io/v1beta3',
parameters: {},
output: {},
steps: [{ id: 'test', name: 'name', action: 'jest-validated-action' }],
});
await expect(runner.execute(task)).rejects.toThrowError(
/Invalid input passed to action jest-validated-action, instance requires property \"foo\"/,
);
});
it('should run the action when the validation passes', async () => {
const task = createMockTaskWithSpec({
apiVersion: 'backstage.io/v1beta3',
parameters: {},
output: {},
steps: [
{
id: 'test',
name: 'name',
action: 'jest-validated-action',
input: { foo: 1 },
},
],
});
await runner.execute(task);
expect(fakeActionHandler).toHaveBeenCalledTimes(1);
});
});
describe('conditionals', () => {
it('should execute steps conditionally', async () => {
const task = createMockTaskWithSpec({
@@ -31,6 +31,7 @@ import { JsonObject, JsonValue } from '@backstage/config';
import { InputError } from '@backstage/errors';
import { PassThrough } from 'stream';
import { isTruthy } from './helper';
import { validate as validateJsonSchema } from 'jsonschema';
type Options = {
workingDirectory: string;
@@ -79,6 +80,8 @@ export class DefaultWorkflowRunner implements WorkflowRunner {
private readonly nunjucks: nunjucks.Environment;
constructor(private readonly options: Options) {
// TODO(blam): Probably need the repo helper here.
// Or we move to returning Objects in the RepoUrlPickerV2 or something?
this.nunjucks = nunjucks.configure({
autoescape: false,
tags: {
@@ -164,7 +167,20 @@ export class DefaultWorkflowRunner implements WorkflowRunner {
const action = this.options.actionRegistry.get(step.action);
const { taskLogger, streamLogger } = createStepLogger({ task, step });
const input = step.input && this.render(step.input, context);
const input = (step.input && this.render(step.input, context)) ?? {};
if (action.schema?.input) {
const validateResult = validateJsonSchema(
input,
action.schema.input,
);
if (!validateResult.valid) {
const errors = validateResult.errors.join(', ');
throw new InputError(
`Invalid input passed to action ${action.id}, ${errors}`,
);
}
}
const tmpDirs = new Array<string>();
const stepOutput: { [outputName: string]: JsonValue } = {};