From 0ecc9a678482929c4fb9037103518d2943e5458b Mon Sep 17 00:00:00 2001 From: Phil Kuang Date: Mon, 12 Sep 2022 15:59:44 -0400 Subject: [PATCH] fix(scaffolder): properly set isDryRun flag in dry-run mode Signed-off-by: Phil Kuang --- .changeset/spicy-lizards-pay.md | 5 ++ .../tasks/NunjucksWorkflowRunner.test.ts | 31 ++++++++++ .../tasks/NunjucksWorkflowRunner.ts | 61 ++++++++++++++----- 3 files changed, 81 insertions(+), 16 deletions(-) create mode 100644 .changeset/spicy-lizards-pay.md diff --git a/.changeset/spicy-lizards-pay.md b/.changeset/spicy-lizards-pay.md new file mode 100644 index 0000000000..285875560c --- /dev/null +++ b/.changeset/spicy-lizards-pay.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Properly set `ctx.isDryRun` when running actions in dry run mode. Also always log action inputs for debugging purposes when running in dry run mode. diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts index 8745b7afdf..24a35078e2 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts @@ -56,9 +56,11 @@ describe('DefaultWorkflowRunner', () => { const createMockTaskWithSpec = ( spec: TaskSpec, secrets?: TaskSecrets, + isDryRun?: boolean, ): TaskContext => ({ spec, secrets, + isDryRun, complete: async () => {}, done: false, emitLog: async () => {}, @@ -85,6 +87,7 @@ describe('DefaultWorkflowRunner', () => { actionRegistry.register({ id: 'jest-validated-action', description: 'Mock action for testing', + supportsDryRun: true, handler: fakeActionHandler, schema: { input: { @@ -640,4 +643,32 @@ describe('DefaultWorkflowRunner', () => { }); }); }); + + describe('dry run', () => { + it('sets isDryRun flag correctly', async () => { + const task = createMockTaskWithSpec( + { + apiVersion: 'scaffolder.backstage.io/v1beta3', + parameters: {}, + output: {}, + steps: [ + { + id: 'test', + name: 'name', + action: 'jest-validated-action', + input: { foo: 1 }, + }, + ], + }, + { + backstageToken: 'secret', + }, + true, + ); + + await runner.execute(task); + + expect(fakeActionHandler.mock.calls[0][0].isDryRun).toEqual(true); + }); + }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts index 6e35f7c69b..009ea1357d 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts @@ -236,25 +236,53 @@ export class NunjucksWorkflowRunner implements WorkflowRunner { const action = this.options.actionRegistry.get(step.action); const { taskLogger, streamLogger } = createStepLogger({ task, step }); - if (task.isDryRun && !action.supportsDryRun) { - task.emitLog( - `Skipping because ${action.id} does not support dry-run`, - { - stepId: step.id, - status: 'skipped', - }, + if (task.isDryRun) { + const redactedSecrets = Object.fromEntries( + Object.entries(task.secrets ?? {}).map(secret => [ + secret[0], + '[REDACTED]', + ]), ); - const outputSchema = action.schema?.output; - if (outputSchema) { - context.steps[step.id] = { - output: generateExampleOutput(outputSchema) as { - [name in string]: JsonValue; + const debugInput = + (step.input && + this.render( + step.input, + { + ...context, + secrets: redactedSecrets, + }, + renderTemplate, + )) ?? + {}; + taskLogger.info( + `Running ${ + action.id + } in dry-run mode with inputs (secrets redacted): ${JSON.stringify( + debugInput, + undefined, + 2, + )}`, + ); + if (!action.supportsDryRun) { + task.emitLog( + `Skipping because ${action.id} does not support dry-run`, + { + stepId: step.id, + status: 'skipped', }, - }; - } else { - context.steps[step.id] = { output: {} }; + ); + const outputSchema = action.schema?.output; + if (outputSchema) { + context.steps[step.id] = { + output: generateExampleOutput(outputSchema) as { + [name in string]: JsonValue; + }, + }; + } else { + context.steps[step.id] = { output: {} }; + } + continue; } - continue; } // Secrets are only passed when templating the input to actions for security reasons @@ -301,6 +329,7 @@ export class NunjucksWorkflowRunner implements WorkflowRunner { }, templateInfo: task.spec.templateInfo, user: task.spec.user, + isDryRun: task.isDryRun, }); // Remove all temporary directories that were created when executing the action