Make automation events and filters consistent and reliable

Aperta
#2,362 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
5/5
Tempo stimato
Più di una settimana
Idoneità per principianti
25/100
Tipo di issue
Funzionalità
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
typescript
Ambito
api, backend

Direzione di ricerca

The remaining work is slice 7 in event-automations/types.ts and event-automations/store.ts, plus event scope data and filters in the service webhook files. Start by reading the trigger design and slices A–D, then inspect the completed changes in #2383 and #2393 for context. Done means filter-only triggers can run without identifiers, saved triggers are converted safely, and the identifier column is removed only after confirming no old rows remain.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Event automations work, but the per-event code and the filter setup have gaps. Events of the same kind from one service carry different data. Some filters save and then never match. The dashboard and Slack show triggers in different ways. This issue tracks the proposed fixes, grouped as separate PRs.

Goals:

  • Events from the same service are consistent. Different services can use different event names when the concepts differ (for example Sentry issue.created and GitHub issue.opened). No rename or migration is planned.
  • Use plain words in the UI and in errors. No internal terms.
  • Use Zod schemas for event data and filter rules so that saved configuration is checked, not assumed.
  • Improve the design where the current pattern is weak. Do not copy an existing pattern only because it is already there.

All paths are from aef8253.

1. Cleanup (no behavior change) — done in #2378
  • Remove the duplicate webhook-secret checks in the GitHub subscribable helpers (packages/junior-github/src/events/{deployment,issue,pull-request,release,repository}.ts) and the webhookSecret input in Vercel. ctx.events.canSubscribe already covers this, because it comes from the plugin isEnabled check. Keep the Vercel check that a commit needs a target.
  • Remove the 4 tests that depend on an empty secret with canSubscribe: true. Add core coverage that isEnabled: false makes canSubscribe false.
  • Remove the copy of the GitHub repository event lists (plugin.ts and events/repository.ts).
  • Export gitHubEventKey and pullRequestTargets from one module. Today they are copied in webhooks/check-suite.ts and webhooks/events.ts.
  • Document that terminal goes only on the exact resource, never on broader scopes.
2. Reject filters that cannot match — done in #2381 and #2394

Today filters are declared per resource type, not per event. If an event does not set a filter field, the filter never matches. For example, GitHub issue.closed with a senderId filter saves and never runs.

  • Add an optional list of events to each match field in the plugin-api schema.
  • Add one shared check in plugin-api. It rejects a filter at save time if a selected event cannot set that field. Use it in the server and the dashboard. The dashboard must not keep its own copy of the filter rules.
  • Flag saved filters that use a field the resource type no longer declares. Show this in the dashboard and in Slack details. #2373 renamed authorUsername, authorEmail, authorRole, requesterUsername, and requesterRole to opener* and authors with no migration, so saved filters on the old fields now never match. A save-time check does not catch them.
  • Support fields with list: true (such as authors) in the shared check. For these fields, a value matches when the event list includes it.
  • Keep GitHub's per-event field rules next to the lazy lookups in webhooks/pull-request-match-data.ts, not in core.
  • Fix a regression from #2381: searchEventTypes kept its own strict copy of the filter-field schema with no events key, so it failed with Unrecognized key: "events" for GitHub filters. It now uses the shared eventMatchFieldSchema from plugin-api. (#2394)
3. Same data for events of the same kind — done in #2383 and #2393
  • GitHub PR comments and reviews set senderId, senderLogin, and mentionsBot, as issue comments do (webhooks/events.ts). This fixes a bug: a repository watch with a senderId filter accepts PR comments but never fires.
  • All GitHub PR events set repo and pullRequest. Issue opened/closed/reopened events set their data.
  • Vercel deployment events set target, commit SHA, and deployment id as data and match fields, not only in the event text.
  • Sentry events set data with fixed value sets, defined in Zod.
  • Split webhooks/events.ts by feature if this work takes it past 1,000 lines. Not needed: the file is 881 lines after #2393.
  • Risk: some saved repository watches with senderId, repo, or pullRequest filters will start to match PR events. Call this out in the PR.
4. How triggers show in the dashboard and Slack — done in #2385
  • One shared formatter for filter conditions, used by the dashboard editor, the automation list, the Slack card, and Slack details. Word the two list cases differently: a list field reads "includes X", and a list of values on a normal field reads "is X or Y". The editor help text (AutomationEventFields.tsx) explains only the second case.
  • Slack automation details show filter conditions. Today a filtered automation looks like it runs on every event.
  • The editor stops showing agent guidance as help text under events.
5. Core and docs — done in #2379 and #2381
  • Replace the timer and slack string checks with watch/automation flags on core's own resource types. Keep these flags private to core.
  • Document what each deployment.* event means per service. Vercel deployment.error matches GitHub deployment.failed, not GitHub deployment.error.
  • Show a clear error when an event is not supported for a resource type. (#2381)
  • Update packages/junior/src/chat/events/README.md with eventKey, objectType, occurredAtMs, the reserved slack namespace, and the steps to add a new event.
6. Structured identifiers instead of regex patterns — dropped, #2390 closed

Item 7 removes identifiers from event automation triggers. Watches get exact identifiers from tool results. So typed identifier parts no longer solve a user problem, and they would break the public plugin API. #2390 is closed without merge.

Today each resource type declares its identifier as a regex pattern (identifier.pattern in plugin-api). The agent and the dashboard must type one magic string, such as owner/repo#123. A regex can only say "does not fit", not which part is wrong, and the editor cannot show separate fields.

  • Replace identifier.pattern with named, typed parts and a template in plugin-api, defined with Zod. For example, parts owner, repo, number and the template {owner}/{repo}#{number}. The rules stay plain JSON, so the dashboard can use them.
  • Core checks the parts and builds the identifier string. Stored keys and exact-match routing do not change.
  • Tools and the dashboard editor take the parts. Errors name the part that is wrong.
  • Move every GitHub, Vercel, Linear and Sentry resource type to parts. Remove the regex patterns.
7. The trigger is the event; scope is a filter — in progress

Today an event automation trigger needs a namespace, a resource type, and one exact identifier (event-automations/types.ts). Matching looks up the exact identifier (event-automations/store.ts). So "any Sentry metric_alert.critical" cannot be set up without an org or project identifier. The trigger should be the service and its events. Org, project, and repo should be optional filters.

Design:

  • An event automation trigger is namespace + events + match. It has no identifier and no resourceType. Resource types stay in the catalog to group events and filters.
  • Check filters against all filter fields of the namespace, with the #2381 rule: every selected event must set the field.
  • Watches keep an exact identifier and do not change. A terminal event completes only the Watch on that exact identifier.
  • Saved identifiers convert to filters, for example owner/repo#123 to repo + pullRequest. A row that cannot convert is blocked with a reason. It never becomes broader.

A review found gaps. The slices below include the fixes.

Slices:

  • A. Scope data first. Every event sets its scope values in data and declares them as filters: GitHub repo, pullRequest, issue, tag, commitSha; Sentry org, projects; Vercel projectId. Use the same case as identifiers. Identifiers are lowercase today, but data.repo is not. Builds on #2383 and #2393.
  • B. Filter-only triggers in core. identifier becomes optional.
    • Lazy match data (collectEventAutomationMatchKeys) must count rows without an identifier. Otherwise GitHub authors and opener* filters never load and never match.
    • Guidance is keyed by namespace + event type, not by resource type.
    • The run limit must not add a duplicate entry for one eventKey. Today each copy of a fanned-out event adds one, so a metric alert on 55 projects can block a filter-only automation after two alerts.
    • Ingest checks event.data.channelId against the destination channel for Slack events. Today only the identifier keeps channel text in its channel.
    • Before filters merge across a namespace, a filter with no events list gets the events of its resource type. Linear teamKey has no list, so the merge fails without this.
    • Load candidate rows once per webhook delivery.
  • C. Convert saved triggers. First stop tools from writing identifiers. Lock each row and record a version. Blocked rows keep a trigger that still parses. The version schema accepts old keys.
  • D. Drop the identifier column after a check shows no old rows.
  • Later, separate: publish one event per occurrence with parentIdentifiers for broader Watches, and delete the plugin terminal strip code. The product goal does not need this.

Decisions:

  • Each event declares if it can be broad ("all repos", "all projects") or which scope filters it requires. A trigger without a required filter is rejected at save time, and the error names the filter. For example, Sentry metric_alert.* can be broad. GitHub comment and review events require repo, because they carry private text and make Junior add a reaction. This is part of slice B.
  • The run limit is per automation and does not change for broad triggers. Each eventKey counts once, so copies of one event do not use more runs.
Not planned

These were reviewed against the code and dropped:

  • One shared fan-out helper. The exact target is not always terminal, and each service fans out differently.
  • One shared timestamp parser. Sentry, Linear, and GitHub send different formats.
  • Lookup tables for state mapping.
  • One definition per resource type, core-built subscribable results, and changes to the published SubscribableResource schema.
  • Human labels, list editing in the dashboard, and match fields in tool results. Revisit after items 2 and 4.
  • Event-key prefix changes, because of retry and idempotency risk.
  • Release events sent to repository watches.

via David Cramer.

--

View Session [Sentry]

Lingua principale
TypeScript
Stelle
385
Fork
42
Merge medio
10h 4m
PR unite (30g)
361

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di getsentry/junior

Tutte le issue di getsentry/junior

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.