fix(core): Show AI Builder draft workflows in workflow list (#29670)

This commit is contained in:
Albert Alises
2026-05-04 10:15:39 +00:00
committed by GitHub
parent be22095646
commit dc52bbd532
2 changed files with 1 additions and 39 deletions
@@ -2,7 +2,7 @@ import { GlobalConfig } from '@n8n/config';
import { In, type SelectQueryBuilder } from '@n8n/typeorm';
import { mock } from 'jest-mock-extended';
import { AiBuilderTemporaryWorkflow, WorkflowEntity } from '../../entities';
import { WorkflowEntity } from '../../entities';
import { mockEntityManager } from '../../utils/test-utils/mock-entity-manager';
import { mockInstance } from '../../utils/test-utils/mock-instance';
import { FolderRepository } from '../folder.repository';
@@ -32,17 +32,9 @@ describe('WorkflowRepository', () => {
jest.resetAllMocks();
queryBuilder = mock<SelectQueryBuilder<WorkflowEntity>>();
const subQueryBuilder = mock<SelectQueryBuilder<AiBuilderTemporaryWorkflow>>();
subQueryBuilder.select.mockReturnThis();
subQueryBuilder.from.mockReturnThis();
subQueryBuilder.where.mockReturnThis();
subQueryBuilder.getQuery.mockReturnValue(
'(SELECT 1 FROM "ai_builder_temporary_workflow" "aitw" WHERE aitw."workflowId" = workflow.id)',
);
queryBuilder.where.mockReturnThis();
queryBuilder.andWhere.mockReturnThis();
queryBuilder.subQuery.mockReturnValue(subQueryBuilder);
queryBuilder.orWhere.mockReturnThis();
queryBuilder.select.mockReturnThis();
queryBuilder.addSelect.mockReturnThis();
@@ -65,18 +57,6 @@ describe('WorkflowRepository', () => {
jest.spyOn(workflowRepository, 'createQueryBuilder').mockReturnValue(queryBuilder);
});
describe('applyAiBuilderTemporaryFilter', () => {
it('hides marker-table rows through a prefix-safe entity subquery', async () => {
await workflowRepository.getMany(['workflow1']);
expect(queryBuilder.subQuery).toHaveBeenCalled();
expect(queryBuilder.subQuery().from).toHaveBeenCalledWith(AiBuilderTemporaryWorkflow, 'aitw');
expect(queryBuilder.andWhere).toHaveBeenCalledWith(
expect.stringContaining('NOT EXISTS (SELECT 1 FROM "ai_builder_temporary_workflow"'),
);
});
});
describe('applyNameFilter', () => {
it('should search for workflows containing all words from the query', async () => {
const workflowIds = ['workflow1'];
@@ -18,7 +18,6 @@ import { SharedWorkflowRepository } from './shared-workflow.repository';
import { WorkflowHistoryRepository } from './workflow-history.repository';
import {
WebhookEntity,
AiBuilderTemporaryWorkflow,
TagEntity,
WorkflowEntity,
WorkflowTagMapping,
@@ -883,23 +882,6 @@ export class WorkflowRepository extends Repository<WorkflowEntity> {
this.applyParentFolderFilter(qb, filter);
this.applyNodeTypesFilter(qb, filter);
this.applyAvailableInMCPFilter(qb, filter);
this.applyAiBuilderTemporaryFilter(qb);
}
/**
* Hide workflows the AI builder created and has not yet promoted to the
* main deliverable. The orchestrator clears the marker on the main at
* build-time and reaps the rest at run-finish, but in the window between
* create and reap, marked rows must not surface in the workflows list.
*/
private applyAiBuilderTemporaryFilter(qb: SelectQueryBuilder<WorkflowEntity>): void {
const markerSubquery = qb
.subQuery()
.select('1')
.from(AiBuilderTemporaryWorkflow, 'aitw')
.where('aitw."workflowId" = workflow.id')
.getQuery();
qb.andWhere(`NOT EXISTS ${markerSubquery}`);
}
private applyAvailableInMCPFilter(