Repository navigation
[DO NOT MERGE] feat(events): Convert saved event automation triggers in the heartbeat - #2447
Draft
sentry-junior[bot] wants to merge 1 commit into
Conversation
Each heartbeat converts up to 50 saved triggers that still have an identifier, under the row lock, and records a version that names Junior. A row that cannot convert keeps its identifier and saves the reason. A dashboard edit that read the row before the conversion fails as a conflict that says Junior changed the trigger. Merge only after a release with #2407 and #2442 has run in production, because older releases cannot read rows with no identifier. Refs #2362 Co-Authored-By: David Cramer <david@sentry.io>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This was referenced Oct 30, 2026
dcramer
added a commit
that referenced
this pull request
Nov 2, 2026
…rs (#2572) Hard cutover on agent input for event automation triggers, as proposed in the [#2442 review](#2442 (review)). An event trigger from `createAutomation` / `updateAutomation` is now `namespace + events + match`. Watches keep exact identifiers. Refs #2362. **Tool input** - `identifier` and `resourceType` are gone from the event trigger schema of both tools. - `updateAutomation` changes `match` key by key: a value sets a filter, `null` removes it, and a filter left out keeps its saved value. So an update can't broaden a trigger by leaving a filter out. A namespace change starts with no filters. - `searchEventTypes` now describes reach in terms of `match`. `reach: "resource"` events (timers, workspace snapshots) are only usable by Watches. **Subscribable results** - `SubscribableResource` gets an optional `match`. It is missing for Watch-only resources. - GitHub fills it from the parts it already has: PR `{repo, pullRequest}`, issue `{repo, issue}`, repo `{repo}`, deployment `{repo, commitSha, environment?}`, release `{repo, tag?}`. Vercel deployment fills `{projectId, target?, commitSha?}`. No identifier parsing. - Linear and Sentry have no subscribable builders. Their match fields (`teamKey`/`issueIdentifier`, `projects`/`issueId`/`alertRuleId`) already cover single-resource scoping, so Sentry does not block dropping the identifier. **Slack channel messages** - `message.posted` moves from `reach: "resource"` to `{ anyOf: ["channelId"] }`. The tools set `channelId` from the destination channel, and `requireSlackChannelMessageScope` still rejects other channels. **Saved triggers with an identifier** - They keep running, and dispatch is unchanged. Tool edits in the same namespace keep the saved identifier. - Known gap until #2447 converts saved rows: if an agent adds a filter that conflicts with a saved identifier, such as `pullRequest: 8` on a row saved as `#7`, the trigger stops matching. Core can't detect that without the plugin conversion that #2447 adds. - The dashboard editor still edits identifiers on saved rows. It should switch over with #2447. **Dedupe:** no change. Runs are keyed on `(automationId, namespace, eventKey)`, so a filter-only automation that matches the PR copy and the repo copy of one webhook still runs once. **Verification** - `pnpm typecheck` and `pnpm lint` pass. - Automation integration suites pass (66 tests), as do the GitHub plugin suite (266) and the Vercel plugin suite (33). - In the full `@sentry/junior` run, these failed in this sandbox: `agent-dispatch-work`, `annotation-cards`, `durable-queue`, `event-wake-delay`, `bot-image-hydration`, and the generated-title assertion in `event-automations`. They also fail on unmodified `main` in the same sandbox (mostly 5s timeouts), so I'm treating them as environment failures. CI is the real check. - I didn't run the evals locally. Updated assertions are in `event-automations/management`, `credentials`, and `guardian/scheduled-work`. <!-- junior-request-attribution:start --> via @dcramer. <!-- junior-request-attribution:end --> <!-- junior-session-footer:start --> <!-- junior-conversation-id:slack%3AC0B595QDZLL%3A1793654465.198809 --> -- [View Session](https://junior-prod.sentry.dev/conversations/slack%3AC0B595QDZLL%3A1793654465.198809) [[Sentry]](https://sentry.sentry.io/explore/conversations/slack%3AC0B595QDZLL%3A1793654465.198809/?project=4510944073809921) <!-- junior-session-footer:end --> --------- Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com> Co-authored-by: David Cramer <23610+dcramer@users.noreply.github.com>
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Do not merge until a release that contains #2407 and #2442 has run in production. Older releases (0.266.0 and before) require
trigger.identifierand parse rows withrows.map. If this backfill runs and the app then rolls back to one of those releases, one converted row breaks automation listing for its whole team. There is no config switch.This PR is stacked on #2442 and contains only the backfill. #2442 shipped the parts that this PR needs: create, update, and dashboard conversion, the plugin
identifierMatchcontract, and the reader foreditedBy: "junior".Refs #2362
What changes
event-automations/trigger-conversion.ts,agent-dispatch/heartbeat.ts). Each heartbeat checks at most 50 saved rows that have an identifier, no saved reason, and the same identifier in the row and in the trigger (listEventAutomationsToConvert). It saves each row with the revision that it read, under the row lock. A row that changed after the read is left for the next heartbeat.triggerWithoutIdentifier. It never gets broader.editedBy: "junior", so the version history shows "Junior", not "Editor unknown".409withchangedBy: "junior", and the editor says "Junior changed this trigger while you were editing." The API checks this as follows: it puts the trigger of the version before Junior's version on the saved row and compares that revision with the revision of the edit. Any other conflict keeps the generic copy.Rollback
editedBy: "junior".Checks (head
89783a006)pnpm typecheckandpnpm lint: pass.any-resource-event-automationscovers the backfill through the real heartbeat:juniorversion,changedBy: "junior",event-automations("delivers the current automation card…"). It fails the same way onmainlocally.via David Cramer.
--
View Session [Sentry]