mirror of
https://github.com/n8n-io/n8n.git
synced 2026-09-24 23:22:38 +08:00
fix: Detect workflow calling itself expression in migration report (#22516)
This commit is contained in:
+33
-2
@@ -1,13 +1,21 @@
|
||||
import type { INode } from 'n8n-workflow';
|
||||
|
||||
import { createNode, createWorkflow } from '../../../__tests__/test-helpers';
|
||||
import { BreakingChangeCategory } from '../../../types';
|
||||
import { WaitNodeSubworkflowRule } from '../wait-node-subworkflow.rule';
|
||||
|
||||
class TestRule extends WaitNodeSubworkflowRule {
|
||||
testExtractCalledWorkflowId(node: INode, callerWorkflowId: string): string | undefined {
|
||||
return super.extractCalledWorkflowId(node, callerWorkflowId);
|
||||
}
|
||||
}
|
||||
|
||||
describe('WaitNodeSubworkflowRule', () => {
|
||||
let rule: WaitNodeSubworkflowRule;
|
||||
let rule: TestRule;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
rule = new WaitNodeSubworkflowRule();
|
||||
rule = new TestRule();
|
||||
rule.reset();
|
||||
});
|
||||
|
||||
@@ -418,4 +426,27 @@ describe('WaitNodeSubworkflowRule', () => {
|
||||
expect(report2.affectedWorkflows).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('extractCalledWorkflowId()', () => {
|
||||
it('should extract the called workflow ID', () => {
|
||||
const node = createNode('ExecuteWorkflow', 'n8n-nodes-base.executeWorkflow', {
|
||||
source: 'database',
|
||||
workflowId: { value: 'sub-wf-1' },
|
||||
});
|
||||
|
||||
const calledWorkflowId = rule.testExtractCalledWorkflowId(node, 'caller-wf-1');
|
||||
expect(calledWorkflowId).toBe('sub-wf-1');
|
||||
});
|
||||
|
||||
it('should return the caller workflow ID if it is an expression', () => {
|
||||
const node = createNode('ExecuteWorkflow', 'n8n-nodes-base.executeWorkflow', {
|
||||
workflowId: '={{ $workflow.id }}',
|
||||
mode: 'each',
|
||||
options: {},
|
||||
});
|
||||
|
||||
const calledWorkflowId = rule.testExtractCalledWorkflowId(node, 'caller-wf-1');
|
||||
expect(calledWorkflowId).toBe('caller-wf-1');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -123,7 +123,7 @@ export class WaitNodeSubworkflowRule implements IBreakingChangeBatchWorkflowRule
|
||||
continue; // Skip if not waiting for sub-workflow completion
|
||||
}
|
||||
|
||||
const calledWorkflowId = this.extractCalledWorkflowId(node);
|
||||
const calledWorkflowId = this.extractCalledWorkflowId(node, workflow.id);
|
||||
|
||||
this.parentWorkflowsCalling.push({
|
||||
parentWorkflowId: workflow.id,
|
||||
@@ -199,7 +199,7 @@ export class WaitNodeSubworkflowRule implements IBreakingChangeBatchWorkflowRule
|
||||
return waitingNodes;
|
||||
}
|
||||
|
||||
private extractCalledWorkflowId(node: INode): string | undefined {
|
||||
protected extractCalledWorkflowId(node: INode, callerWorkflowId: string): string | undefined {
|
||||
const source = node.parameters.source as string | undefined;
|
||||
|
||||
// Only handle database source - for other sources we can't determine the workflow ID statically
|
||||
@@ -213,7 +213,8 @@ export class WaitNodeSubworkflowRule implements IBreakingChangeBatchWorkflowRule
|
||||
if (typeof workflowId === 'string') {
|
||||
// Check if it's an expression (starts with =)
|
||||
if (workflowId.startsWith('=')) {
|
||||
return undefined; // Can't evaluate expressions statically
|
||||
// Can't evaluate expressions statically
|
||||
return this.isWorkflowItselfExpression(workflowId) ? callerWorkflowId : undefined;
|
||||
}
|
||||
return workflowId;
|
||||
}
|
||||
@@ -223,7 +224,8 @@ export class WaitNodeSubworkflowRule implements IBreakingChangeBatchWorkflowRule
|
||||
if (typeof value === 'string') {
|
||||
// Check if it's an expression (starts with =)
|
||||
if (value.startsWith('=')) {
|
||||
return undefined; // Can't evaluate expressions statically
|
||||
// Can't evaluate expressions statically
|
||||
return this.isWorkflowItselfExpression(value) ? callerWorkflowId : undefined;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -231,4 +233,8 @@ export class WaitNodeSubworkflowRule implements IBreakingChangeBatchWorkflowRule
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private isWorkflowItselfExpression(workflowIdExpression: string): boolean {
|
||||
return workflowIdExpression.replace('{{ ', '{{').replace(' }}', '}}') === '={{$workflow.id}}';
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user