From 62d1fe301cc652b399170acd91a7c1edeb6c8fdb Mon Sep 17 00:00:00 2001 From: Stephen Glass Date: Tue, 18 Jun 2024 01:25:03 -0400 Subject: [PATCH] Fix user entity not being fetched for scaffolder dry runner Signed-off-by: Stephen Glass --- .changeset/young-fishes-lie.md | 5 ++++ .../src/scaffolder/dryrun/createDryRunner.ts | 5 ++++ .../src/service/router.test.ts | 28 +++++++++++++++++++ .../scaffolder-backend/src/service/router.ts | 12 ++++++++ 4 files changed, 50 insertions(+) create mode 100644 .changeset/young-fishes-lie.md diff --git a/.changeset/young-fishes-lie.md b/.changeset/young-fishes-lie.md new file mode 100644 index 0000000000..769d046375 --- /dev/null +++ b/.changeset/young-fishes-lie.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Fix user entity not being fetched for scaffolder dry runner diff --git a/plugins/scaffolder-backend/src/scaffolder/dryrun/createDryRunner.ts b/plugins/scaffolder-backend/src/scaffolder/dryrun/createDryRunner.ts index 6b8caf5a3d..c993e0d46d 100644 --- a/plugins/scaffolder-backend/src/scaffolder/dryrun/createDryRunner.ts +++ b/plugins/scaffolder-backend/src/scaffolder/dryrun/createDryRunner.ts @@ -38,12 +38,17 @@ import { BackstageCredentials, resolveSafeChildPath, } from '@backstage/backend-plugin-api'; +import type { UserEntity } from '@backstage/catalog-model'; interface DryRunInput { spec: TaskSpec; secrets?: TaskSecrets; directoryContents: SerializedFile[]; credentials: BackstageCredentials; + user?: { + entity?: UserEntity; + ref?: string; + }; } interface DryRunResult { diff --git a/plugins/scaffolder-backend/src/service/router.test.ts b/plugins/scaffolder-backend/src/service/router.test.ts index 8ba26c68a4..c776f563d7 100644 --- a/plugins/scaffolder-backend/src/service/router.test.ts +++ b/plugins/scaffolder-backend/src/service/router.test.ts @@ -691,6 +691,34 @@ data: {"id":1,"taskId":"a-random-id","type":"completion","createdAt":"","body":{ expect(subscriber!.closed).toBe(true); }); }); + + describe('POST /v2/dry-run', () => { + it('should get user entity', async () => { + const mockToken = mockCredentials.user.token(); + const mockTemplate = getMockTemplate(); + + const catalogSpy = jest.spyOn(catalogClient, 'getEntityByRef'); + + await request(app) + .post('/v2/dry-run') + .set('Authorization', `Bearer ${mockToken}`) + .send({ + template: mockTemplate, + values: { + requiredParameter1: 'required-value-1', + requiredParameter2: 'required-value-2', + }, + directoryContents: [], + }); + + expect(catalogSpy).toHaveBeenCalledTimes(1); + + expect(catalogSpy).toHaveBeenCalledWith( + 'user:default/mock', + expect.anything(), + ); + }); + }); }); describe('providing an identity api', () => { diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index 384b9f5340..84cdac0c3f 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -730,6 +730,14 @@ export async function createRouter( targetPluginId: 'catalog', }); + const userEntityRef = auth.isPrincipal(credentials, 'user') + ? credentials.principal.userEntityRef + : undefined; + + const userEntity = userEntityRef + ? await catalogClient.getEntityByRef(userEntityRef, { token }) + : undefined; + for (const parameters of [template.spec.parameters ?? []].flat()) { const result = validate(body.values, parameters); if (!result.valid) { @@ -750,6 +758,10 @@ export async function createRouter( steps, output: template.spec.output ?? {}, parameters: body.values as JsonObject, + user: { + entity: userEntity as UserEntity, + ref: userEntityRef, + }, }, directoryContents: (body.directoryContents ?? []).map(file => ({ path: file.path,