From c4c85db64bb78f02e276c5c3a708bb587a440942 Mon Sep 17 00:00:00 2001 From: tristantr Date: Mon, 1 Jun 2026 15:30:51 +0200 Subject: [PATCH] feat(deploy-to-hub): thin /triggers proxy to forward trigger bulk-sync to Hub Mirrors the existing /scripts, /flows, /apps thin proxies. Forwards { triggers, workspace_slug } to Hub's POST /workspaces/[slug]/triggers bulk-replace endpoint, with the same require_admin + HUB_DEV_TOKEN guardrails. Lets the frontend push trigger stubs in a single round-trip after the items they reference have landed on the Hub. Co-Authored-By: Claude Opus 4.7 (1M context) --- backend/windmill-api/src/hub_publish.rs | 35 +++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/backend/windmill-api/src/hub_publish.rs b/backend/windmill-api/src/hub_publish.rs index 9ff57d7667..ffa3986d54 100644 --- a/backend/windmill-api/src/hub_publish.rs +++ b/backend/windmill-api/src/hub_publish.rs @@ -24,6 +24,7 @@ pub fn workspaced_service() -> Router { .route("/flows/{flow_id}/recording", post(publish_flow_recording)) .route("/resource_types", post(publish_resource_type)) .route("/resources", post(publish_resources)) + .route("/triggers", post(publish_triggers)) } #[derive(Deserialize)] @@ -235,6 +236,40 @@ async fn publish_resources( .await } +#[derive(Deserialize, Serialize)] +struct PublishTriggerBody { + path: String, + kind: String, + #[serde(skip_serializing_if = "Option::is_none")] + summary: Option, + #[serde(skip_serializing_if = "Option::is_none")] + description: Option, + config: serde_json::Value, + #[serde(skip_serializing_if = "Option::is_none")] + script_ask_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] + flow_id: Option, +} + +#[derive(Deserialize, Serialize)] +struct PublishTriggersBody { + triggers: Vec, + workspace_slug: String, +} + +async fn publish_triggers( + authed: ApiAuthed, + Path(_workspace): Path, + Json(body): Json, +) -> Result { + require_admin(authed.is_admin, &authed.username)?; + forward_to_hub( + &format!("/workspaces/{}/triggers", body.workspace_slug), + &body, + ) + .await +} + async fn forward_to_hub(path: &str, body: &T) -> Result<(StatusCode, String), Error> { let hub_token = std::env::var("HUB_DEV_TOKEN") .map_err(|_| Error::BadRequest("HUB_DEV_TOKEN not set".into()))?;