From f5fb2829f7f6c4fabf8f2a63e86a5d7cbc1425a5 Mon Sep 17 00:00:00 2001 From: John Collier Date: Wed, 4 Mar 2026 23:00:02 -0500 Subject: [PATCH] address review feedback Signed-off-by: John Collier --- .../actions/listScaffolderTasksAction.test.ts | 47 ++++++++++++++++++- .../src/actions/listScaffolderTasksAction.ts | 30 ++++++++---- .../scaffolder-node/report-testUtils.api.md | 2 +- plugins/scaffolder-node/report.api.md | 2 +- .../scaffolder-node/src/scaffolderService.ts | 8 ++-- 5 files changed, 74 insertions(+), 15 deletions(-) diff --git a/plugins/scaffolder-backend/src/actions/listScaffolderTasksAction.test.ts b/plugins/scaffolder-backend/src/actions/listScaffolderTasksAction.test.ts index bad0b366b6..20eac54cf8 100644 --- a/plugins/scaffolder-backend/src/actions/listScaffolderTasksAction.test.ts +++ b/plugins/scaffolder-backend/src/actions/listScaffolderTasksAction.test.ts @@ -199,7 +199,7 @@ describe('createListScaffolderTasksAction', () => { ); }); - it('should filter tasks by status when status is provided', async () => { + it('should filter tasks by a single status when status is provided', async () => { const mockActionsRegistry = actionsRegistryServiceMock(); const mockAuth = mockServices.auth.mock(); const mockScaffolderService = scaffolderServiceMock.mock(); @@ -244,6 +244,51 @@ describe('createListScaffolderTasksAction', () => { }); }); + it('should filter tasks by multiple statuses when an array is provided', async () => { + const mockActionsRegistry = actionsRegistryServiceMock(); + const mockAuth = mockServices.auth.mock(); + const mockScaffolderService = scaffolderServiceMock.mock(); + const matchingTasks = generateMockTasks().tasks.filter( + t => t.status === 'completed' || t.status === 'failed', + ); + + mockScaffolderService.listTasks.mockResolvedValue({ + items: matchingTasks as ScaffolderTask[], + totalItems: matchingTasks.length, + }); + + createListScaffolderTasksAction({ + actionsRegistry: mockActionsRegistry, + auth: mockAuth, + scaffolderService: mockScaffolderService, + }); + + const result = await mockActionsRegistry.invoke({ + id: 'test:list-scaffolder-tasks', + input: { status: ['completed', 'failed'] }, + }); + + expect(mockScaffolderService.listTasks).toHaveBeenCalledWith( + { + createdBy: undefined, + limit: undefined, + offset: undefined, + status: ['completed', 'failed'], + }, + expect.objectContaining({ credentials: expect.anything() }), + ); + expect(result.output).toEqual({ + tasks: matchingTasks.map(task => ({ + id: task.id, + spec: task.spec, + status: task.status, + createdAt: task.createdAt, + lastHeartbeatAt: task.lastHeartbeatAt, + })), + totalTasks: matchingTasks.length, + }); + }); + it('should throw NotAllowedError when owned is true without user identity', async () => { const mockActionsRegistry = actionsRegistryServiceMock(); const mockAuth = mockServices.auth.mock(); diff --git a/plugins/scaffolder-backend/src/actions/listScaffolderTasksAction.ts b/plugins/scaffolder-backend/src/actions/listScaffolderTasksAction.ts index 2b05b8aee1..3f3a0eed04 100644 --- a/plugins/scaffolder-backend/src/actions/listScaffolderTasksAction.ts +++ b/plugins/scaffolder-backend/src/actions/listScaffolderTasksAction.ts @@ -40,7 +40,7 @@ This allows you to list scaffolder tasks that have been created. Each task has a unique id, specification, and status (one of open, processing, completed, failed, cancelled, skipped). Each task includes a timestamp for when it was created, and an optional last heartbeat timestamp indicating the most recent activity. Set owned to true to return only tasks created by the current user; omit or set to false for all tasks the credentials can see. -Pagination is supported via limit and offset. +Filtering by one or multiple statuses is supported. Pagination is supported via limit and offset. `, schema: { input: z => @@ -66,16 +66,28 @@ Pagination is supported via limit and offset. .describe('The offset to start from for pagination') .optional(), status: z - .enum([ - 'open', - 'processing', - 'completed', - 'failed', - 'cancelled', - 'skipped', + .union([ + z.enum([ + 'open', + 'processing', + 'completed', + 'failed', + 'cancelled', + 'skipped', + ]), + z.array( + z.enum([ + 'open', + 'processing', + 'completed', + 'failed', + 'cancelled', + 'skipped', + ]), + ), ]) .optional() - .describe('Filter tasks by status'), + .describe('Filter tasks by status, or an array of statuses'), }), output: z => z diff --git a/plugins/scaffolder-node/report-testUtils.api.md b/plugins/scaffolder-node/report-testUtils.api.md index 51bc0d0d5e..0dcbd460a2 100644 --- a/plugins/scaffolder-node/report-testUtils.api.md +++ b/plugins/scaffolder-node/report-testUtils.api.md @@ -80,7 +80,7 @@ export interface ScaffolderService { createdBy?: string; limit?: number; offset?: number; - status?: ScaffolderTaskStatus; + status?: ScaffolderTaskStatus | ScaffolderTaskStatus[]; }, options: ScaffolderServiceRequestOptions, ): Promise<{ diff --git a/plugins/scaffolder-node/report.api.md b/plugins/scaffolder-node/report.api.md index b27c8c8cfe..95d821a218 100644 --- a/plugins/scaffolder-node/report.api.md +++ b/plugins/scaffolder-node/report.api.md @@ -391,7 +391,7 @@ export interface ScaffolderService { createdBy?: string; limit?: number; offset?: number; - status?: ScaffolderTaskStatus; + status?: ScaffolderTaskStatus | ScaffolderTaskStatus[]; }, options: ScaffolderServiceRequestOptions, ): Promise<{ diff --git a/plugins/scaffolder-node/src/scaffolderService.ts b/plugins/scaffolder-node/src/scaffolderService.ts index 74d301b718..cb3e8dd675 100644 --- a/plugins/scaffolder-node/src/scaffolderService.ts +++ b/plugins/scaffolder-node/src/scaffolderService.ts @@ -83,7 +83,7 @@ export interface ScaffolderService { createdBy?: string; limit?: number; offset?: number; - status?: ScaffolderTaskStatus; + status?: ScaffolderTaskStatus | ScaffolderTaskStatus[]; }, options: ScaffolderServiceRequestOptions, ): Promise<{ items: ScaffolderTask[]; totalItems: number }>; @@ -186,7 +186,7 @@ class DefaultScaffolderService implements ScaffolderService { createdBy?: string; limit?: number; offset?: number; - status?: ScaffolderTaskStatus; + status?: ScaffolderTaskStatus | ScaffolderTaskStatus[]; }, options: ScaffolderServiceRequestOptions, ): Promise<{ items: ScaffolderTask[]; totalItems: number }> { @@ -204,7 +204,9 @@ class DefaultScaffolderService implements ScaffolderService { params.set('offset', String(request.offset)); } if (request.status !== undefined) { - params.set('status', request.status); + for (const s of [request.status].flat()) { + params.append('status', s); + } } const query = params.toString();