fix(automations): fire Linear triggers for every member, not only the one who connected

Closed
KI
2h ago
+75-18

Links

Summary

  • Linear-triggered automations now fire for every member of the organization, not only for the member who connected Linear.
  • Keeps the #7317 guarantee that two connections to one Linear workspace do not run the same automation twice.

Why / Context

#7317 set ownerUserId: connection.connectedByUserId on every Linear dispatch, the same narrowing Google uses. That fits Google, where a connection is one person's mailbox. It does not fit Linear: a connection receives the whole Linear workspace's events. So a member who never connected Linear never gets their Linear automations to fire. Example: Kiet's issue.assigned automation has zero runs, and Harshith's copy with the same filter fires.

Just removing the narrowing brings back the bug #7317 fixed. processDelivery records one automation_events row per connection, so with two connections an unpinned trigger would match twice.

How It Works

  • processDelivery picks one lead connection per Superset organization: the first by id, in the order accountConnections already returns.
  • The lead's event fires unpinned triggers and triggers pinned to it, the same as before #7317.
  • Every other connection's event is dispatched with a new pinnedOnly: true, so dispatchMatchingTriggers only considers triggers whose connectionId is that connection.
  • pinnedOnly is stored in the dispatch_input jsonb, so redispatchUndispatched handles retried events the same way. No migration is needed.

Manual QA Checklist

Not done yet. I did not send a real Linear webhook through this end to end.

  • Org with one Linear connection (member A): a matching automation owned by member B, who has no connection, fires once.
  • Same org, member A's automation pinned to A's connection fires once.
  • Org with two connections (A, B): an unpinned trigger fires once; triggers pinned to A and to B each fire once.

Testing

  • bun test src/app/api/integrations/linear src/lib/automations (in apps/api): 41 pass
  • bun run typecheck (in apps/api): clean
  • biome check on the changed files: clean
  • processDelivery.test.ts: replaced the "narrows to the connection owner" test with three tests: only the lead fires unpinned triggers, nothing filters by owner, and each organization has its own lead. With the lead logic broken, two of the three fail.
  • The pinnedOnly SQL branch in dispatchMatchingTriggers has no unit test, and that file has no test suite.

Known Limitations

  • If the lead connection is disconnected while an event is still being retried, a different connection becomes the lead, and an unpinned trigger can run twice for that one event.
  • "Me" scopes still resolve through the owner's own Linear identity, so a member without a Linear connection must pick people explicitly.

Summary by cubic

Fixes Linear-triggered automations so they fire for every organization member, not only the member who connected the Linear workspace. A Linear connection receives the whole workspace's events, so previously a member without their own connection never got their Linear triggers to run. Preserves the #7317 guarantee that two connections to the same workspace don't run the same automation twice.

  • One connection per organization leads the event and fires unpinned triggers; every other connection only fires triggers pinned to it, so each matching trigger runs once.
  • The new pinnedOnly flag is stored in the dispatch input, so retried deliveries keep the same behavior; no migration needed.
  • Known limitation: if the lead connection is removed mid-retry, a different connection becomes lead and an unpinned trigger can run twice for that one event.
  • End-to-end Linear webhook QA not yet done, and the pinnedOnly SQL branch has no unit test.

Summary by CodeRabbit

  • Automation Updates
    • Linear events now match automations based on their connection: one connection per organization can match general automations, while other connections match only automations pinned to them.
    • This matching behavior is preserved when event delivery is retried.