feat(shared,trpc): save triggers as a set with the automation

Merged
SA
3mo ago
+611-61

Replaces the per-trigger CRUD approach in #6531 (now draft). Triggers are edited as part of the automation, so the surface is a replace-the-set on automation.create/update.

No migration.

Shared validation

Lives in @superset/shared/automation-triggers, imported by both the editor and the API, so the form blocks Save on exactly what the server would reject rather than reimplementing the rules.

It deliberately has two levels:

  • draftTriggerSchema accepts a half-configured trigger. The editor has to be able to hold "Draft opened in [Select Repos]" with nothing chosen yet — if the schema refused to represent that, the form couldn't hold its own in-progress state.
  • describeTriggerProblems reports what blocks Save, per trigger and per field, so a message can sit next to the control it belongs to. summarizeTriggerProblems produces the banner.

The messages match the mockups: "Some triggers need additional configuration" and "Specify at least one repository."

It also catches more than one schedule per automation, which the partial unique index enforces in the database — better as a message next to the row than a constraint violation at save time.

Matched by id, not cleared and reinserted

A trigger row carries state the editor never sees: a webhook's signing key, and a schedule's next run. Clearing and reinserting would silently roll a key someone had already configured upstream, and reschedule an automation that was only renamed.

So rows present in the set are updated in place, rows absent are deleted, and the next run is only recomputed when the recurrence actually changed.

GitHub configs are a union on the event

The filters differ per event — "Any Comment by [Anyone] on a PR by [Anyone] in [Repos]" carries two independent actor scopes where "Draft opened" carries one. A single flat config with one actor can't express that, so the config discriminates on event.

includeForks stays the literal false: fork payloads carry attacker-controlled content into a checkout the agent runs in, so enabling it should be a schema change with a threat model attached.

Verified against a real database

The actual saveTriggerSet executed against Postgres 16, not reasoned about:

Initial save creates the set2 triggers
Webhook signing key survives an unrelated savepreserved
Schedule not rescheduled by an unrelated savepreserved
Row ids stable across savesstable
Trigger dropped from the set is deleteddeleted
Recurrence change does reschedulereschedules
Unconfigured GitHub trigger rejected server-siderejected

Plus the shared validation itself: a half-configured trigger parses but reports a problem; a comment event requires both actors; includeForks: true, unknown events, and an unknown kind are all rejected.

Compatibility

Top-level rrule still works and folds into a single schedule trigger, so the CLI, SDK, MCP and desktop keep working until they move to sending a set. Same expand-contract shape as the column migration.

Typecheck, lint and the full suite pass.

Next

The editor UI, then webhook ingestion so event triggers actually fire.


Summary by cubic

Saves automation triggers as a replace-the-set on create/update and makes event-only automations first‑class. Previously list/get assumed every automation had a schedule; now schedule is optional and responses reflect what was actually saved.

  • API: createAutomation/updateAutomation accept optional triggers: DraftTrigger[] (max 25). Create requires either triggers or rrule; if rrule is provided, timezone is required. If triggers are absent, the legacy top‑level rrule folds into a single schedule trigger. Invalid sets return 400 with per‑field problems.
  • Schedule handling: list/get/getAutomationForUser use a left join; schedule fields in responses are nullable. Create/update now build schedule fields from saved triggers, not the input.
  • Validation (@superset/shared/automation-triggers): shared draft+save checks; enforces at most one schedule; GitHub config discriminates on event; Slack reaction_added requires an emoji; actor is anyone | me | specific people.
  • Persistence: new saveTriggerSet matches rows by id, deletes dropped rows, and only recomputes nextRunAt when the schedule’s recurrence changes. Webhook signing keys and existing nextRunAt are preserved across unrelated edits.
  • Packages: packages/shared exports ./automation-triggers. No migration.

Summary by CodeRabbit

  • New Features
    • Added support for configuring up to 25 automation triggers, including schedules and event-driven integrations.
    • Automation creation and updates now save, update, and remove trigger configurations reliably.
    • Event-only automations can be created without a schedule.
    • Existing schedule configurations remain supported for compatibility.
    • Added validation for trigger requirements and provider-specific settings, with clear summaries of configuration issues.