Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 35 additions & 1 deletion packages/cli/src/webhooks/test-webhooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ import * as WebhookHelpers from '@/webhooks/webhook-helpers';
import * as WorkflowExecuteAdditionalData from '@/workflow-execute-additional-data';
import type { WorkflowRequest } from '@/workflows/workflow.request';

const SINGLE_WEBHOOK_TRIGGERS = [
'n8n-nodes-base.telegramTrigger',
'n8n-nodes-base.slackTrigger',
'n8n-nodes-base.facebookLeadAdsTrigger',
];

/**
* Service for handling the execution of webhooks of manual executions
* that use the [Test URL](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.webhook/#webhook-urls).
Expand Down Expand Up @@ -266,12 +272,15 @@ export class TestWebhooks implements IWebhookManager {
async needsWebhook(options: {
userId: string;
workflowEntity: IWorkflowBase;
workflowActiveData: { active: boolean; activeVersionId: string | null };
additionalData: IWorkflowExecuteAdditionalData;
runData?: IRunData;
pushRef?: string;
destinationNode?: string;
triggerToStartFrom?: WorkflowRequest.FullManualExecutionFromKnownTriggerPayload['triggerToStartFrom'];
}) {
console.log('Checking if test webhook is needed');
console.log(options.workflowActiveData);
const {
userId,
workflowEntity,
Expand All @@ -284,37 +293,62 @@ export class TestWebhooks implements IWebhookManager {

if (!workflowEntity.id) throw new WorkflowMissingIdError(workflowEntity);

console.log('workflowEntity is: ', workflowEntity);

const workflow = this.toWorkflow(workflowEntity);

console.log('workflowActiveData:', options.workflowActiveData);

const workflowIsActive =
options.workflowActiveData.active || options.workflowActiveData.activeVersionId;

console.log('workflowIsActive:', workflowIsActive);

let webhooks = WebhookHelpers.getWorkflowWebhooks(
workflow,
additionalData,
destinationNode,
true,
);

console.log('Found webhooks:', webhooks);

// If we have a preferred trigger with data, we don't have to listen for a
// webhook.
if (triggerToStartFrom?.data) {
console.log('Preferred trigger with data found, no webhook needed: ', triggerToStartFrom);
return false;
}

// If we have a preferred trigger without data we only want to listen for
// that trigger, not the other ones.
if (triggerToStartFrom) {
console.log(
'Preferred trigger without data found, filtering webhooks to only listen for that trigger: ',
triggerToStartFrom,
);
webhooks = webhooks.filter((w) => w.node === triggerToStartFrom.name);
}

if (!webhooks.some((w) => w.webhookDescription.restartWebhook !== true)) {
console.log('All webhooks are restartable, no webhook needed');
return false; // no webhooks found to start a workflow
}

if (
workflowIsActive &&
webhooks.find((w) => SINGLE_WEBHOOK_TRIGGERS.includes(workflow.getNode(w.node)?.type ?? ''))
) {
throw new Error('Single webhook triggers are not supported for test executions.');
}

const timeout = setTimeout(
async () => await this.cancelWebhook(workflow.id),
TEST_WEBHOOK_TIMEOUT,
);

for (const webhook of webhooks) {
console.log('Activating test webhook for node:', webhook);
const key = this.registrations.toKey(webhook);
const registrationByKey = await this.registrations.get(key);

Expand Down Expand Up @@ -492,7 +526,7 @@ export class TestWebhooks implements IWebhookManager {
name: workflowEntity.name,
nodes: workflowEntity.nodes,
connections: workflowEntity.connections,
active: false,
active: workflowEntity.active,
nodeTypes: this.nodeTypes,
staticData: {},
settings: workflowEntity.settings,
Expand Down
7 changes: 7 additions & 0 deletions packages/cli/src/workflows/workflow-execution.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@ export class WorkflowExecutionService {
return false;
}

const workflowActiveData = {
active: payload.workflowData.active,
activeVersionId: payload.workflowData.activeVersionId,
};

// For manual testing always set to not active
payload.workflowData.active = false;
payload.workflowData.activeVersionId = null;
Expand Down Expand Up @@ -223,6 +228,7 @@ export class WorkflowExecutionService {
const needsWebhook = await this.testWebhooks.needsWebhook({
userId: user.id,
workflowEntity: payload.workflowData,
workflowActiveData,
additionalData,
pushRef,
triggerToStartFrom: payload.triggerToStartFrom,
Expand Down Expand Up @@ -274,6 +280,7 @@ export class WorkflowExecutionService {
const needsWebhook = await this.testWebhooks.needsWebhook({
userId: user.id,
workflowEntity: payload.workflowData,
workflowActiveData,
additionalData,
pushRef,
destinationNode: payload.destinationNode,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import {
CHAT_TRIGGER_NODE_TYPE,
IN_PROGRESS_EXECUTION_ID,
SINGLE_WEBHOOK_TRIGGERS,

Check failure on line 27 in packages/frontend/editor-ui/src/app/composables/useRunWorkflow.ts

View workflow job for this annotation

GitHub Actions / Lint / Lint

'SINGLE_WEBHOOK_TRIGGERS' is defined but never used
} from '@/app/constants';

import { useRootStore } from '@n8n/stores/useRootStore';
Expand Down Expand Up @@ -286,7 +286,7 @@
return true;
});

const singleWebhookTrigger =
/*const singleWebhookTrigger =
options.triggerNode === undefined
? // if there is no chosen trigger we check all triggers
triggers.find((node) => SINGLE_WEBHOOK_TRIGGERS.includes(node.type))
Expand All @@ -309,7 +309,7 @@
type: 'error',
});
return undefined;
}
}*/

const startRunData: IStartRunData = {
workflowData,
Expand Down
Loading