From bc88dc4bd2bfa3e2e6430c10a251fd274445a06b Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Mon, 27 Jul 2026 08:25:03 -0400 Subject: [PATCH] fix(core): Fix MCP workflow update failing for active workflows on SQLite (#34964) --- .../src/workflows/workflow-finder.service.ts | 1 + .../workflows/workflow-finder.service.test.ts | 64 +++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 packages/cli/test/integration/workflows/workflow-finder.service.test.ts diff --git a/packages/cli/src/workflows/workflow-finder.service.ts b/packages/cli/src/workflows/workflow-finder.service.ts index c8205c04a3b..8f4bcb7694e 100644 --- a/packages/cli/src/workflows/workflow-finder.service.ts +++ b/packages/cli/src/workflows/workflow-finder.service.ts @@ -61,6 +61,7 @@ export class WorkflowFinderService { relations: { workflow: true }, select: { workflowId: true, + projectId: true, workflow: { id: true, versionId: true, updatedAt: true }, }, }); diff --git a/packages/cli/test/integration/workflows/workflow-finder.service.test.ts b/packages/cli/test/integration/workflows/workflow-finder.service.test.ts new file mode 100644 index 00000000000..bb96963fc0e --- /dev/null +++ b/packages/cli/test/integration/workflows/workflow-finder.service.test.ts @@ -0,0 +1,64 @@ +import { createWorkflow, testDb } from '@n8n/backend-test-utils'; +import { GLOBAL_MEMBER_ROLE, GLOBAL_OWNER_ROLE, type User } from '@n8n/db'; +import { Container } from '@n8n/di'; + +import { WorkflowFinderService } from '@/workflows/workflow-finder.service'; + +import { createUser } from '../shared/db/users'; + +let owner: User; +let member: User; +let anotherMember: User; +let workflowFinderService: WorkflowFinderService; + +beforeAll(async () => { + await testDb.init(); + owner = await createUser({ role: GLOBAL_OWNER_ROLE }); + member = await createUser({ role: GLOBAL_MEMBER_ROLE }); + anotherMember = await createUser({ role: GLOBAL_MEMBER_ROLE }); + workflowFinderService = Container.get(WorkflowFinderService); +}); + +beforeEach(async () => { + await testDb.truncate(['WorkflowEntity', 'SharedWorkflow']); +}); + +afterAll(async () => { + await testDb.terminate(); +}); + +describe('WorkflowFinderService', () => { + describe('findWorkflowHeadForUser', () => { + it('should return the workflow head for a user with a project-scoped role', async () => { + const workflow = await createWorkflow({}, member); + + const head = await workflowFinderService.findWorkflowHeadForUser(workflow.id, member, [ + 'workflow:publish', + ]); + + expect(head?.versionId).toBe(workflow.versionId); + expect(head?.updatedAt).toBeInstanceOf(Date); + }); + + it('should return the workflow head for a user with a global scope', async () => { + const workflow = await createWorkflow({}, member); + + const head = await workflowFinderService.findWorkflowHeadForUser(workflow.id, owner, [ + 'workflow:publish', + ]); + + expect(head?.versionId).toBe(workflow.versionId); + expect(head?.updatedAt).toBeInstanceOf(Date); + }); + + it('should return null for a user without access to the workflow', async () => { + const workflow = await createWorkflow({}, member); + + const head = await workflowFinderService.findWorkflowHeadForUser(workflow.id, anotherMember, [ + 'workflow:publish', + ]); + + expect(head).toBeNull(); + }); + }); +});