From 49676f2cae769098e83976c0e047a5118ca7e8b9 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Sat, 30 Dec 2023 18:51:08 +0000 Subject: [PATCH 01/19] recomitting trigger another automation work --- .../FlowChart/ActionModal.svelte | 1 - packages/server/src/automations/actions.ts | 4 + .../server/src/automations/steps/trigger.ts | 75 +++++++++++++++++++ .../types/src/documents/app/automation.ts | 1 + 4 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 packages/server/src/automations/steps/trigger.ts diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ActionModal.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ActionModal.svelte index 15dd864168..a0da8e455a 100644 --- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ActionModal.svelte +++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ActionModal.svelte @@ -23,7 +23,6 @@ let selectedAction let actionVal let actions = Object.entries($automationStore.blockDefinitions.ACTION) - $: collectBlockExists = checkForCollectStep($selectedAutomation) const disabled = () => { diff --git a/packages/server/src/automations/actions.ts b/packages/server/src/automations/actions.ts index 81cf4d8176..7025a2f64c 100644 --- a/packages/server/src/automations/actions.ts +++ b/packages/server/src/automations/actions.ts @@ -15,6 +15,7 @@ import * as delay from "./steps/delay" import * as queryRow from "./steps/queryRows" import * as loop from "./steps/loop" import * as collect from "./steps/collect" +import * as trigger from "./steps/trigger" import env from "../environment" import { AutomationStepSchema, @@ -41,6 +42,7 @@ const ACTION_IMPLS: Record< FILTER: filter.run, QUERY_ROWS: queryRow.run, COLLECT: collect.run, + TRIGGER_AUTOMATION: trigger.run, // these used to be lowercase step IDs, maintain for backwards compat discord: discord.run, slack: slack.run, @@ -62,6 +64,7 @@ export const BUILTIN_ACTION_DEFINITIONS: Record = QUERY_ROWS: queryRow.definition, LOOP: loop.definition, COLLECT: collect.definition, + TRIGGER: trigger.definition, // these used to be lowercase step IDs, maintain for backwards compat discord: discord.definition, slack: slack.definition, @@ -102,6 +105,7 @@ export async function getActionDefinitions() { /* istanbul ignore next */ export async function getAction(stepId: string) { + console.log(stepId) if (ACTION_IMPLS[stepId] != null) { return ACTION_IMPLS[stepId] } diff --git a/packages/server/src/automations/steps/trigger.ts b/packages/server/src/automations/steps/trigger.ts new file mode 100644 index 0000000000..7624bef817 --- /dev/null +++ b/packages/server/src/automations/steps/trigger.ts @@ -0,0 +1,75 @@ +import { + AutomationActionStepId, + AutomationStepSchema, + AutomationStepInput, + AutomationStepType, + AutomationIOType, + AutomationFeature, + AutomationResults, + Automation, +} from "@budibase/types" +import * as triggers from "../triggers" +import { db as dbCore, context } from "@budibase/backend-core" + +export const definition: AutomationStepSchema = { + name: "Trigger Automation", + tagline: "Triggers an automation synchronously", + icon: "Sync", + description: "Triggers an automation synchronously", + type: AutomationStepType.ACTION, + internal: true, + features: {}, + stepId: AutomationActionStepId.TRIGGER, + inputs: {}, + schema: { + inputs: { + properties: { + automationId: { + type: AutomationIOType.STRING, + title: "Automation ID to trigger", + }, + }, + required: ["automationId"], + }, + outputs: { + properties: { + success: { + type: AutomationIOType.BOOLEAN, + description: "Whether the automation was successful", + }, + value: { + type: AutomationIOType.OBJECT, + description: "Automation Result", + }, + }, + required: ["success", "value"], + }, + }, +} + +export async function run({ inputs }: AutomationStepInput) { + console.log("??: " + inputs.automationId) + console.log("???DSAASDFAFSDFDSFDS") + if (!inputs.automationId) { + return { + success: false, + } + } else { + const db = context.getAppDB() + let automation = await db.get(inputs.automationId) + + const response: AutomationResults = await triggers.externalTrigger( + automation, + { + fields: {}, + timeout: 120000, + }, + { getResponses: true } + ) + + return { + success: true, + value: response, + } + } +} diff --git a/packages/types/src/documents/app/automation.ts b/packages/types/src/documents/app/automation.ts index 88ce5e9b9a..bbaa74bb14 100644 --- a/packages/types/src/documents/app/automation.ts +++ b/packages/types/src/documents/app/automation.ts @@ -61,6 +61,7 @@ export enum AutomationActionStepId { LOOP = "LOOP", COLLECT = "COLLECT", OPENAI = "OPENAI", + TRIGGER = "TRIGGER", // these used to be lowercase step IDs, maintain for backwards compat discord = "discord", slack = "slack", From 734ad2c1ae7d9d7fa6f396dc7e9138c13fc45039 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Wed, 3 Jan 2024 11:59:15 +0000 Subject: [PATCH 02/19] further work for triggering automations from other automations --- .../builder/src/builderStore/store/automation/index.js | 1 + .../AutomationBuilder/FlowChart/ActionModal.svelte | 10 +++++++++- .../AutomationBuilder/FlowChart/TestDataModal.svelte | 2 ++ packages/builder/src/constants/backend/automations.js | 1 + packages/builder/src/stores/portal/licensing.js | 5 +++++ packages/pro | 2 +- packages/server/src/automations/actions.ts | 2 +- packages/server/src/automations/steps/trigger.ts | 10 ++++++---- packages/types/src/sdk/licensing/feature.ts | 1 + 9 files changed, 27 insertions(+), 7 deletions(-) diff --git a/packages/builder/src/builderStore/store/automation/index.js b/packages/builder/src/builderStore/store/automation/index.js index af83f73dc6..aecdff0246 100644 --- a/packages/builder/src/builderStore/store/automation/index.js +++ b/packages/builder/src/builderStore/store/automation/index.js @@ -155,6 +155,7 @@ const automationActions = store => ({ await store.actions.save(newAutomation) }, test: async (automation, testData) => { + console.log(testData) const result = await API.testAutomation({ automationId: automation?._id, testData, diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ActionModal.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ActionModal.svelte index a0da8e455a..6c84875996 100644 --- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ActionModal.svelte +++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ActionModal.svelte @@ -19,6 +19,7 @@ export let lastStep let syncAutomationsEnabled = $licensing.syncAutomationsEnabled + let triggerAutomationsEnabled = $licensing.triggerAutomationsEnabled let collectBlockAllowedSteps = [TriggerStepID.APP, TriggerStepID.WEBHOOK] let selectedAction let actionVal @@ -35,6 +36,10 @@ disabled: !lastStep || !syncAutomationsEnabled || collectBlockExists, message: collectDisabledMessage(), }, + TRIGGER: { + disabled: !triggerAutomationsEnabled, + message: collectDisabledMessage(), + }, } } @@ -98,6 +103,9 @@ notifications.error("Error saving automation") } } + + let lockedFeatures = [ActionStepID.COLLECT, ActionStepID.TRIGGER] + $: console.log {action.name} - {#if isDisabled && !syncAutomationsEnabled && action.stepId === ActionStepID.COLLECT} + {#if isDisabled && !syncAutomationsEnabled && !triggerAutomationsEnabled && lockedFeatures.includes(action.stepId)}
Business diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte index 76def72bf6..70162a9368 100644 --- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte +++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte @@ -46,6 +46,8 @@ } const testAutomation = async () => { + console.log(testData) + console.log($selectedAutomation) try { await automationStore.actions.test($selectedAutomation, testData) $automationStore.showTestPanel = true diff --git a/packages/builder/src/constants/backend/automations.js b/packages/builder/src/constants/backend/automations.js index f89a126d3c..f26e2a7424 100644 --- a/packages/builder/src/constants/backend/automations.js +++ b/packages/builder/src/constants/backend/automations.js @@ -21,6 +21,7 @@ export const ActionStepID = { QUERY_ROWS: "QUERY_ROWS", LOOP: "LOOP", COLLECT: "COLLECT", + TRIGGER: "TRIGGER", // these used to be lowercase step IDs, maintain for backwards compat discord: "discord", slack: "slack", diff --git a/packages/builder/src/stores/portal/licensing.js b/packages/builder/src/stores/portal/licensing.js index 3197822e53..daf4b0ce86 100644 --- a/packages/builder/src/stores/portal/licensing.js +++ b/packages/builder/src/stores/portal/licensing.js @@ -125,6 +125,10 @@ export const createLicensingStore = () => { const syncAutomationsEnabled = license.features.includes( Constants.Features.SYNC_AUTOMATIONS ) + const triggerAutomationsEnabled = license.features.includes( + Constants.Features.SYNC_AUTOMATIONS + ) + const perAppBuildersEnabled = license.features.includes( Constants.Features.APP_BUILDERS ) @@ -147,6 +151,7 @@ export const createLicensingStore = () => { auditLogsEnabled, enforceableSSO, syncAutomationsEnabled, + triggerAutomationsEnabled, isViewPermissionsEnabled, perAppBuildersEnabled, } diff --git a/packages/pro b/packages/pro index 992486c100..82de3443fd 160000 --- a/packages/pro +++ b/packages/pro @@ -1 +1 @@ -Subproject commit 992486c10044a7495496b97bdf5f454d4020bfba +Subproject commit 82de3443fd03b272555d23c42ead3a611302277d diff --git a/packages/server/src/automations/actions.ts b/packages/server/src/automations/actions.ts index 7025a2f64c..2fb08f754f 100644 --- a/packages/server/src/automations/actions.ts +++ b/packages/server/src/automations/actions.ts @@ -42,7 +42,7 @@ const ACTION_IMPLS: Record< FILTER: filter.run, QUERY_ROWS: queryRow.run, COLLECT: collect.run, - TRIGGER_AUTOMATION: trigger.run, + TRIGGER: trigger.run, // these used to be lowercase step IDs, maintain for backwards compat discord: discord.run, slack: slack.run, diff --git a/packages/server/src/automations/steps/trigger.ts b/packages/server/src/automations/steps/trigger.ts index 7624bef817..f85c24e963 100644 --- a/packages/server/src/automations/steps/trigger.ts +++ b/packages/server/src/automations/steps/trigger.ts @@ -26,7 +26,11 @@ export const definition: AutomationStepSchema = { properties: { automationId: { type: AutomationIOType.STRING, - title: "Automation ID to trigger", + title: "Automation ID", + }, + timeout: { + type: AutomationIOType.NUMBER, + title: "Timeout (ms)", }, }, required: ["automationId"], @@ -48,8 +52,6 @@ export const definition: AutomationStepSchema = { } export async function run({ inputs }: AutomationStepInput) { - console.log("??: " + inputs.automationId) - console.log("???DSAASDFAFSDFDSFDS") if (!inputs.automationId) { return { success: false, @@ -62,7 +64,7 @@ export async function run({ inputs }: AutomationStepInput) { automation, { fields: {}, - timeout: 120000, + timeout: inputs.timeout * 1000 || 120000, }, { getResponses: true } ) diff --git a/packages/types/src/sdk/licensing/feature.ts b/packages/types/src/sdk/licensing/feature.ts index 732a4a6c77..65d852e627 100644 --- a/packages/types/src/sdk/licensing/feature.ts +++ b/packages/types/src/sdk/licensing/feature.ts @@ -9,6 +9,7 @@ export enum Feature { BRANDING = "branding", SCIM = "scim", SYNC_AUTOMATIONS = "syncAutomations", + TRIGGER_AUTOMATION = "triggerAutomation", APP_BUILDERS = "appBuilders", OFFLINE = "offline", EXPANDED_PUBLIC_API = "expandedPublicApi", From 6507b6ec54af391147cd457b256be3819b4992a1 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Wed, 3 Jan 2024 12:01:13 +0000 Subject: [PATCH 03/19] remove logging --- .../automation/AutomationBuilder/FlowChart/TestDataModal.svelte | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte index 70162a9368..76def72bf6 100644 --- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte +++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte @@ -46,8 +46,6 @@ } const testAutomation = async () => { - console.log(testData) - console.log($selectedAutomation) try { await automationStore.actions.test($selectedAutomation, testData) $automationStore.showTestPanel = true From 1437ce2e666301e2ad636799e3aa9b1a362ee65e Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Wed, 3 Jan 2024 15:28:07 +0000 Subject: [PATCH 04/19] some small ux updates --- .../AutomationBuilder/FlowChart/ActionModal.svelte | 7 +++---- packages/server/src/automations/steps/trigger.ts | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ActionModal.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ActionModal.svelte index 6c84875996..c335329844 100644 --- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ActionModal.svelte +++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ActionModal.svelte @@ -19,11 +19,13 @@ export let lastStep let syncAutomationsEnabled = $licensing.syncAutomationsEnabled - let triggerAutomationsEnabled = $licensing.triggerAutomationsEnabled + let triggerAutomationsEnabled = true let collectBlockAllowedSteps = [TriggerStepID.APP, TriggerStepID.WEBHOOK] let selectedAction let actionVal let actions = Object.entries($automationStore.blockDefinitions.ACTION) + let lockedFeatures = [ActionStepID.COLLECT, ActionStepID.TRIGGER] + $: collectBlockExists = checkForCollectStep($selectedAutomation) const disabled = () => { @@ -103,9 +105,6 @@ notifications.error("Error saving automation") } } - - let lockedFeatures = [ActionStepID.COLLECT, ActionStepID.TRIGGER] - $: console.log Date: Fri, 5 Jan 2024 16:12:31 +0000 Subject: [PATCH 05/19] test and pr comments --- .../builderStore/store/automation/index.js | 1 - .../FlowChart/ActionModal.svelte | 2 +- packages/server/src/automations/actions.ts | 1 - .../src/automations/tests/trigger.spec.ts | 33 +++++++++++++++ .../server/src/tests/utilities/structures.ts | 40 ++++++++++++++++++- 5 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 packages/server/src/automations/tests/trigger.spec.ts diff --git a/packages/builder/src/builderStore/store/automation/index.js b/packages/builder/src/builderStore/store/automation/index.js index aecdff0246..af83f73dc6 100644 --- a/packages/builder/src/builderStore/store/automation/index.js +++ b/packages/builder/src/builderStore/store/automation/index.js @@ -155,7 +155,6 @@ const automationActions = store => ({ await store.actions.save(newAutomation) }, test: async (automation, testData) => { - console.log(testData) const result = await API.testAutomation({ automationId: automation?._id, testData, diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ActionModal.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ActionModal.svelte index c335329844..0c97853dd6 100644 --- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ActionModal.svelte +++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ActionModal.svelte @@ -19,7 +19,7 @@ export let lastStep let syncAutomationsEnabled = $licensing.syncAutomationsEnabled - let triggerAutomationsEnabled = true + let triggerAutomationsEnabled = $licensing.triggerAutomationsEnabled let collectBlockAllowedSteps = [TriggerStepID.APP, TriggerStepID.WEBHOOK] let selectedAction let actionVal diff --git a/packages/server/src/automations/actions.ts b/packages/server/src/automations/actions.ts index 2fb08f754f..a3997ad21c 100644 --- a/packages/server/src/automations/actions.ts +++ b/packages/server/src/automations/actions.ts @@ -105,7 +105,6 @@ export async function getActionDefinitions() { /* istanbul ignore next */ export async function getAction(stepId: string) { - console.log(stepId) if (ACTION_IMPLS[stepId] != null) { return ACTION_IMPLS[stepId] } diff --git a/packages/server/src/automations/tests/trigger.spec.ts b/packages/server/src/automations/tests/trigger.spec.ts new file mode 100644 index 0000000000..e8a2cc9345 --- /dev/null +++ b/packages/server/src/automations/tests/trigger.spec.ts @@ -0,0 +1,33 @@ +jest.spyOn(global.console, "error") + +import * as setup from "./utilities" +import * as automation from "../index" + +describe("Test triggering an automation from another automation", () => { + let config = setup.getConfig() + + beforeAll(async () => { + await automation.init() + await config.init() + }) + + afterAll(async () => { + await automation.shutdown() + setup.afterAll() + }) + + it("should trigger an other server log automation", async () => { + let newAutomation = await config.createAutomation() + + const inputs: any = { automationId: newAutomation._id, timeout: 12000 } + const res = await setup.runStep(setup.actions.TRIGGER.stepId, inputs) + // Check if the SERVER_LOG step was successful + expect(res.value[1].outputs.success).toBe(true) + }) + + it("should fail gracefully if the automation id is incorrect", async () => { + const inputs: any = { automationId: null, timeout: 12000 } + const res = await setup.runStep(setup.actions.TRIGGER.stepId, inputs) + expect(res.success).toBe(false) + }) +}) diff --git a/packages/server/src/tests/utilities/structures.ts b/packages/server/src/tests/utilities/structures.ts index 83be8b6d58..ce08011e76 100644 --- a/packages/server/src/tests/utilities/structures.ts +++ b/packages/server/src/tests/utilities/structures.ts @@ -146,7 +146,45 @@ export function basicAutomation(appId?: string): Automation { }, }, }, - steps: [], + steps: [ + { + stepId: AutomationActionStepId.SERVER_LOG, + name: "Backend log", + tagline: "Console log a value in the backend", + icon: "Monitoring", + description: "Logs the given text to the server (using console.log)", + internal: true, + features: { + LOOPING: true, + }, + inputs: { + text: "sdfsdf", + }, + schema: { + inputs: { + properties: { + text: { + type: "string", + title: "Text to log", + }, + }, + required: ["text"], + }, + outputs: { + properties: { + success: { + description: "Whether the action was successful", + }, + message: { + description: "What was output", + }, + }, + required: ["success", "message"], + }, + }, + id: "y8lkZbeSe", + }, + ], }, type: "automation", appId: appId!, From 78ef231e03c1854a534144f8b77ead1a1fa33a50 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Wed, 10 Jan 2024 16:34:52 +0000 Subject: [PATCH 06/19] fix issue with being able to select any automation to trigger --- .../SetupPanel/AutomationBlockSetup.svelte | 10 ++- .../SetupPanel/AutomationSelector.svelte | 86 +++++++++++++++++++ .../server/src/automations/steps/trigger.ts | 23 +++-- .../types/src/documents/app/automation.ts | 2 + 4 files changed, 114 insertions(+), 7 deletions(-) create mode 100644 packages/builder/src/components/automation/SetupPanel/AutomationSelector.svelte diff --git a/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte b/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte index 158ecd8281..b9400c0d86 100644 --- a/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte +++ b/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte @@ -28,6 +28,7 @@ import CodeEditorModal from "./CodeEditorModal.svelte" import QuerySelector from "./QuerySelector.svelte" import QueryParamSelector from "./QueryParamSelector.svelte" + import AutomationSelector from "./AutomationSelector.svelte" import CronBuilder from "./CronBuilder.svelte" import Editor from "components/integration/QueryEditor.svelte" import ModalBindableInput from "components/common/bindings/ModalBindableInput.svelte" @@ -286,7 +287,8 @@ value.customType !== "code" && value.customType !== "queryParams" && value.customType !== "cron" && - value.customType !== "triggerSchema" + value.customType !== "triggerSchema" && + value.customType !== "automationFields" ) } @@ -421,6 +423,12 @@ on:change={e => onChange(e, key)} value={inputData[key]} /> + {:else if value.customType === "automationFields"} + onChange(e, key)} + value={inputData[key]} + {bindings} + /> {:else if value.customType === "queryParams"} onChange(e, key)} diff --git a/packages/builder/src/components/automation/SetupPanel/AutomationSelector.svelte b/packages/builder/src/components/automation/SetupPanel/AutomationSelector.svelte new file mode 100644 index 0000000000..ae45bfd8a1 --- /dev/null +++ b/packages/builder/src/components/automation/SetupPanel/AutomationSelector.svelte @@ -0,0 +1,86 @@ + + +
+ +
+