From d6c642b170b9547fe1d8db190affa35b305c9c8a Mon Sep 17 00:00:00 2001 From: hugocasa Date: Thu, 23 Apr 2026 18:30:18 +0200 Subject: [PATCH] feat: add Azure Event Grid triggers (#8888) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add Azure Event Grid triggers (EE) Introduces a new enterprise trigger kind `azure` that supports three modes via a single unified trigger type: - basic_push: Azure Event Grid basic — custom topics, system topics (Storage, Resource Manager, Key Vault, etc.), domains (push only) - namespace_push: Event Grid Namespace topics (CloudEvents over HTTP push) - namespace_pull: Event Grid Namespace topics (HTTP pull with lock-token ack/reject for dead-lettering) Auth uses a Service Principal resource (tenant_id, client_id, client_secret, subscription_id). Subscriptions are created in CloudEvents 1.0 schema so the push webhook handler and the pull listener share one payload parser. Backend - New crate `windmill-trigger-azure` (OSS stubs + EE impl symlinked from windmill-ee-private) - Migration `azure_trigger` table with CHECK constraints enforcing mode/columns coherence - `TriggerKind::Azure`, `JobTriggerKind::Azure`, `DeployedObject::AzureTrigger` variants - Push route `/api/azure/w/{workspace}/*path` handles classic Event Grid SubscriptionValidation handshake and CloudEvents 1.0 abuse-protection OPTIONS handshake - Optional inbound JWT validation (audience check only for v1) - Feature flag `azure_trigger` propagated through windmill-api, windmill-store (resource helper), and added to ee_core Frontend - `triggers/azure/` editor with mode toggle (basic/namespace-push/ namespace-pull) and per-mode config (topic ARM id / namespace + topic name / subscription / filters / push auth / pull options) - Registered in icon map, display names, save functions, badge, wrapper, editor, add-trigger menu OpenAPI - `AzureTrigger`, `AzureTriggerData`, `AzureMode`, `AzureSubscriptionMode`, `AzureDeliveryConfig`, `TestAzureConnection` schemas; `/azure_triggers/*` endpoints; client regenerated Co-Authored-By: Claude Opus 4.7 (1M context) * chore: update ee-repo-ref to eaa7c3a9cb37a9ccc93f10a2535d929365acd2d8 This commit updates the EE repository reference after PR #541 was merged in windmill-ee-private. Previous ee-repo-ref: 9689014e8c12c36c1059fd8fa5758d550b8b8bc9 New ee-repo-ref: eaa7c3a9cb37a9ccc93f10a2535d929365acd2d8 Automated by sync-ee-ref workflow. * feat(azure-trigger): secret-auth push, ARM discovery, capture isolation, CLI + parity Frontend: - Split mode selector into Namespace/Basic + Pull/Push - ARM resource dropdowns (namespaces, Basic topics, namespace topics) populated from the service principal; cascade with stale-selection reset on SP / edition change - Remove stale authenticate toggle + audience input (server-managed push_auth_config has replaced them) - Azure listing page: "Create from template" button; "Also delete Azure subscription" toggle in the delete modal; simplified trigger label falling back to path - AzureCapture.svelte: "Test subscription name" with -wm-capture suffix - CompareWorkspaces.svelte: wire Azure for fork/compare - Drop Trigger-deployed/event-loss warning (capture subscription is isolated with -wm-capture) Backend: - Shared-secret push auth (see EE crate for detail) - JSONB push_auth_config column (renamed from delivery_config), #[serde(skip)] so clients/CLI/exports never see it - Drop redundant enabled column; mode supersedes - Azure capture infra: AzureTriggerConfig + set_azure_trigger_config + azure_payload route + TriggerKind::Azure arm; PT15M queue TTL on capture subscriptions so they bound storage after tab close - Granular ACLs, users offboarding, trash, git-sync deployed-object: all include azure_trigger CLI: - Add azure to TRIGGER_TYPES, pushObj dispatch, getTypeStrFromPath, trigger commands (get/update/create/list/template), sync delete switch + regex; e2e test for `trigger new --kind azure` - system_prompts: SCHEMA_MAPPINGS + schema_names include AzureTrigger; auto-generated/* regenerated Skill: - .claude/skills/adding-a-trigger/ checklist covering every file that needs editing when wiring a new trigger type (learned from this PR) ee-repo-ref bumped to b0e490cbf3724b7b64c6a5b010e3bdf24acd873c. Co-Authored-By: Claude Opus 4.7 (1M context) * fix(azure-trigger): ci — ShareModal Kind + regenerated system_prompts - frontend/src/lib/components/ShareModal.svelte: add 'azure_trigger' to the Kind type so the listing page's "Permissions" action compiles (ts2345 — caught by npm_check on CI, missed by fast-check locally). - system_prompts/auto-generated/: regenerate to drop the stale delivery_config / AzureDeliveryConfig fields from the Azure schema (check-freshness on CI). Co-Authored-By: Claude Opus 4.7 (1M context) * refactor(azure-trigger): use workspace constant_time_eq crate Drop hand-rolled constant-time compare in favour of the workspace constant_time_eq crate (same one used by http_trigger_auth). ee-repo-ref bumped to 9659382d47286e7f7f66d01b6f5dd8d4ed34848b. Co-Authored-By: Claude Opus 4.7 (1M context) * fix(azure-trigger): pass placeholder + disabled via inputProps `TextInput`'s `placeholder` and `disabled` go through its `inputProps` prop — CI's `npm run check` caught the stale top-level passing that `npm run check:fast` missed. Align with the DefaultEmailConfigSection pattern. Co-Authored-By: Claude Opus 4.7 (1M context) * fix(azure-trigger): correct LATEST_GIT_SYNC_SCRIPT_PATH version to 28213 The hub deploy of the azure-aware sync-script is version 28213, not 28214. Backend was pinning a non-existent hub script, which broke the git_sync_e2e suite (every deploy's sync step 404'd). Co-Authored-By: Claude Opus 4.7 (1M context) * fix(azure-trigger): add azure_triggers to token scope selector + skill - windmill-api/src/token.rs: `build_trigger_scope_domains` was missing `("azure_triggers", "Azure Event Grid")`, so the CreateToken UI's scope selector didn't surface azure_triggers:read/write. Backend already had `ScopeDomain::AzureTriggers` wired (scopes.rs), this just exposes it. - .claude/skills/adding-a-trigger/SKILL.md: capture both scope-related files under the hardcoded-arrays section so future triggers don't miss the UI surface. Co-Authored-By: Claude Opus 4.7 (1M context) * docs(adding-a-trigger-skill): clarify token.rs scope effect Not a regression — nothing was working before. Skipping TRIGGER_DOMAINS just means the scope works via API/CLI but has no UI checkbox. * docs(adding-a-trigger-skill): trim token.rs bullet * fix(azure-trigger): regen openapi-deref + swap textarea for TextInput - Run build_openapi.sh to regenerate openapi-deref.{yaml,json} with the 12 azure_triggers paths + schemas. These files are served by the runtime (include_str! in windmill-api/src/lib.rs) to external SDK consumers; without this regen the new endpoints wouldn't be advertised. - Replace the raw