From f1ca3caf1c92242c3f4c660d68db407d56fe44bb Mon Sep 17 00:00:00 2001 From: hugocasa Date: Wed, 10 Sep 2025 14:22:28 +0200 Subject: [PATCH] cli and git sync (#6568) --- backend/windmill-api/src/workspaces_export.rs | 18 ++++++++++++++++++ cli/src/commands/sync/sync.ts | 12 ++++++++++-- cli/src/commands/trigger/trigger.ts | 9 +++++++++ cli/src/types.ts | 7 ++++++- 4 files changed, 43 insertions(+), 3 deletions(-) diff --git a/backend/windmill-api/src/workspaces_export.rs b/backend/windmill-api/src/workspaces_export.rs index 7758e024b7..fb7afaccaa 100644 --- a/backend/windmill-api/src/workspaces_export.rs +++ b/backend/windmill-api/src/workspaces_export.rs @@ -29,6 +29,7 @@ use crate::{ feature = "sqs_trigger", feature = "gcp_trigger", feature = "nats", + feature = "smtp", ), feature = "private" ) @@ -689,6 +690,23 @@ pub(crate) async fn tarball_workspace( .await?; } } + + #[cfg(all(feature = "enterprise", feature = "smtp", feature = "private"))] + { + use crate::triggers::email::EmailTrigger; + let handler = EmailTrigger; + let email_triggers = handler.list_triggers(&mut *tx, &w_id, None).await?; + + for trigger in email_triggers { + let trigger_str = &to_string_without_metadata(&trigger, false, None).unwrap(); + archive + .write_to_archive( + &trigger_str, + &format!("{}.email_trigger.json", trigger.base.path), + ) + .await?; + } + } } if include_users.unwrap_or(false) { diff --git a/cli/src/commands/sync/sync.ts b/cli/src/commands/sync/sync.ts index a7b2fd4660..4ab1af2252 100644 --- a/cli/src/commands/sync/sync.ts +++ b/cli/src/commands/sync/sync.ts @@ -689,7 +689,8 @@ export async function elementsToMap( path.endsWith(".postgres_trigger" + ext) || path.endsWith(".mqtt_trigger" + ext) || path.endsWith(".sqs_trigger" + ext) || - path.endsWith(".gcp_trigger" + ext)) + path.endsWith(".gcp_trigger" + ext) || + path.endsWith(".email_trigger" + ext)) ) continue; if (!skips.includeUsers && path.endsWith(".user" + ext)) continue; @@ -1044,7 +1045,8 @@ function getOrderFromPath(p: string) { typ == "postgres_trigger" || typ == "mqtt_trigger" || typ == "sqs_trigger" || - typ == "gcp_trigger" + typ == "gcp_trigger" || + typ == "email_trigger" ) { return 8; } else if (typ == "variable") { @@ -2137,6 +2139,12 @@ export async function push( path: removeSuffix(target, ".gcp_trigger.json"), }); break; + case "email_trigger": + await wmill.deleteEmailTrigger({ + workspace: workspaceId, + path: removeSuffix(target, ".email_trigger.json"), + }); + break; case "variable": await wmill.deleteVariable({ workspace: workspaceId, diff --git a/cli/src/commands/trigger/trigger.ts b/cli/src/commands/trigger/trigger.ts index 7e3afd9288..cd52265b52 100644 --- a/cli/src/commands/trigger/trigger.ts +++ b/cli/src/commands/trigger/trigger.ts @@ -8,6 +8,7 @@ import { PostgresTrigger, SqsTrigger, WebsocketTrigger, + EmailTrigger, } from "../../../gen/types.gen.ts"; import { colors, Command, log, SEP, Table } from "../../../deps.ts"; import { @@ -31,6 +32,7 @@ type Trigger = { mqtt: MqttTrigger; sqs: SqsTrigger; gcp: GcpTrigger; + email: EmailTrigger }; type TriggerFile = Omit< @@ -65,6 +67,7 @@ async function getTrigger( mqtt: wmill.getMqttTrigger, sqs: wmill.getSqsTrigger, gcp: wmill.getGcpTrigger, + email: wmill.getEmailTrigger, }; const triggerFunction = triggerFunctions[triggerType]; @@ -95,6 +98,7 @@ async function updateTrigger( gcp: async (args) => { throw new Error("GCP triggers are not supported yet"); }, + email: wmill.updateEmailTrigger, }; const triggerFunction = triggerFunctions[triggerType]; await triggerFunction({ workspace, path, requestBody: trigger }); @@ -123,6 +127,7 @@ async function createTrigger( gcp: async (args) => { throw new Error("GCP triggers are not supported yet"); }, + email: wmill.createEmailTrigger, }; const triggerFunction = triggerFunctions[triggerType]; await triggerFunction({ workspace, path, requestBody: trigger }); @@ -205,6 +210,9 @@ async function list(opts: GlobalOptions) { const gcpTriggers = await wmill.listGcpTriggers({ workspace: workspace.workspaceId, }); + const emailTriggers = await wmill.listEmailTriggers({ + workspace: workspace.workspaceId, + }); const triggers = [ ...httpTriggers.map((x) => ({ path: x.path, kind: "http" })), ...websocketTriggers.map((x) => ({ path: x.path, kind: "websocket" })), @@ -214,6 +222,7 @@ async function list(opts: GlobalOptions) { ...mqttTriggers.map((x) => ({ path: x.path, kind: "mqtt" })), ...sqsTriggers.map((x) => ({ path: x.path, kind: "sqs" })), ...gcpTriggers.map((x) => ({ path: x.path, kind: "gcp" })), + ...emailTriggers.map((x) => ({ path: x.path, kind: "email" })), ]; new Table() diff --git a/cli/src/types.ts b/cli/src/types.ts index 123f132662..ec3600b0a8 100644 --- a/cli/src/types.ts +++ b/cli/src/types.ts @@ -53,7 +53,8 @@ export const TRIGGER_TYPES = [ 'postgres', 'mqtt', 'sqs', - 'gcp' + 'gcp', + 'email', ] as const; export type GlobalOptions = { @@ -180,6 +181,8 @@ export async function pushObj( await pushTrigger("sqs", workspace, p, befObj, newObj); } else if (typeEnding === "gcp_trigger") { await pushTrigger("gcp", workspace, p, befObj, newObj); + } else if (typeEnding === "email_trigger") { + await pushTrigger("email", workspace, p, befObj, newObj); } else if (typeEnding === "user") { await pushWorkspaceUser(workspace, p, befObj, newObj); } else if (typeEnding === "group") { @@ -230,6 +233,7 @@ export function getTypeStrFromPath( | "mqtt_trigger" | "sqs_trigger" | "gcp_trigger" + | "email_trigger" | "user" | "group" | "settings" @@ -281,6 +285,7 @@ export function getTypeStrFromPath( typeEnding === "mqtt_trigger" || typeEnding === "sqs_trigger" || typeEnding === "gcp_trigger" || + typeEnding === "email_trigger" || typeEnding === "user" || typeEnding === "group" || typeEnding === "settings" ||