Skip to content

Fix visibility change early return and dualreview cleanup

9ef30aa
Select commit
Loading
Failed to load commit list.
Closed

feat: Add Linear action item syncing for incidents #139

Fix visibility change early return and dualreview cleanup
9ef30aa
Select commit
Loading
Failed to load commit list.
@sentry/warden / warden: code-review completed Apr 30, 2026 in 1m 28s

3 issues

code-review: Found 3 issues (1 medium, 2 low)

Medium

Race condition between get_or_create and Linear API call can leave orphaned ExternalLink - `src/firetower/incidents/hooks.py:449-454`

The function uses get_or_create to claim the ExternalLink row, but if the LinearService().create_issue call raises an exception or returns None, the link is deleted. However, between the get_or_create and the delete, a concurrent request could see the placeholder link with empty url and incorrectly assume Linear is already configured. This is a side-effect/concurrency concern in incident creation flow.

Low

incident.save(update_fields=["linear_parent_issue_id"]) may overwrite concurrent updates - `src/firetower/incidents/hooks.py:478-479`

Saving the incident with update_fields after a network call to Linear bypasses any optimistic concurrency. If another process modified the incident concurrently (e.g., title updates triggering Linear sync described in the PR), only linear_parent_issue_id is persisted, but the in-memory incident may have stale data for other fields. While update_fields limits the columns written, the incident object used elsewhere in on_incident_created is not refreshed, which could cause downstream hooks to operate on stale data.

LinearService instantiated per hook call - `src/firetower/incidents/hooks.py:759`

Both on_title_changed and on_visibility_changed instantiate a new LinearService() on every invocation. If the constructor performs OAuth token acquisition or other expensive setup, this could create unnecessary overhead and additional API calls per title/visibility change. Consider reusing a module-level service or caching the auth token.


Duration: 1m 25s · Tokens: 453.0k in / 2.2k out · Cost: $2.51 (+merge: $0.00)

Annotations

Check warning on line 454 in src/firetower/incidents/hooks.py

See this annotation in the file changed.

@sentry-warden sentry-warden / warden: code-review

Race condition between get_or_create and Linear API call can leave orphaned ExternalLink

The function uses get_or_create to claim the ExternalLink row, but if the LinearService().create_issue call raises an exception or returns None, the link is deleted. However, between the get_or_create and the delete, a concurrent request could see the placeholder link with empty url and incorrectly assume Linear is already configured. This is a side-effect/concurrency concern in incident creation flow.