diff --git a/.changeset/fix-scaffolder-task-events-after-zero.md b/.changeset/fix-scaffolder-task-events-after-zero.md new file mode 100644 index 0000000000..5ff9bc2de6 --- /dev/null +++ b/.changeset/fix-scaffolder-task-events-after-zero.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Fix handling of `after=0` in task events endpoint diff --git a/plugins/scaffolder-backend/src/service/router.test.ts b/plugins/scaffolder-backend/src/service/router.test.ts index 223909f2c9..5b463ee75b 100644 --- a/plugins/scaffolder-backend/src/service/router.test.ts +++ b/plugins/scaffolder-backend/src/service/router.test.ts @@ -1572,6 +1572,46 @@ data: {"id":1,"taskId":"a-random-id","type":"completion","createdAt":"","body":{ }); expect(subscriber!.closed).toBe(true); }); + + it('should handle after=0 query param correctly', async () => { + const { router, taskBroker } = await createTestRouter(); + (taskBroker.get as jest.Mocked['get']).mockResolvedValue({ + id: 'a-random-id', + spec: {} as any, + status: 'completed', + createdAt: '', + secrets: { + __initiatorCredentials: JSON.stringify(credentials), + }, + createdBy: '', + }); + let subscriber: ZenObservable.SubscriptionObserver<{ + events: SerializedTaskEvent[]; + }>; + ( + taskBroker.event$ as jest.Mocked['event$'] + ).mockImplementation(() => { + return new ObservableImpl(observer => { + subscriber = observer; + observer.next({ events: [] }); + }); + }); + + const response = await request(router) + .get('/v2/tasks/a-random-id/events') + .query({ after: 0 }); + + expect(response.status).toEqual(200); + expect(response.body).toEqual([]); + + expect(taskBroker.event$).toHaveBeenCalledTimes(1); + expect(taskBroker.event$).toHaveBeenCalledWith({ + taskId: 'a-random-id', + after: 0, + }); + expect(subscriber!.closed).toBe(true); + }); + it('disallows users from seeing events for tasks they do not own', async () => { const { permissions, router, taskBroker } = await createTestRouter(); diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index 32b89c7c5e..10d81cc515 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -960,7 +960,8 @@ export async function createRouter( isTaskAuthorized, }); - const after = Number(req.query.after) || undefined; + const after = + req.query.after !== undefined ? Number(req.query.after) : undefined; // cancel the request after 30 seconds. this aligns with the recommendations of RFC 6202. const timeout = setTimeout(() => {