Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/sentry/integrations/tasks/sync_status_inbound.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from sentry.constants import ObjectStatus
from sentry.integrations.models.integration import Integration
from sentry.integrations.services.integration import integration_service
from sentry.models.activity import Activity
from sentry.models.group import Group, GroupStatus
from sentry.models.groupresolution import GroupResolution
from sentry.models.organization import Organization
Expand Down Expand Up @@ -275,6 +276,16 @@ def sync_status_inbound(
if not created:
resolution.update(datetime=django_timezone.now(), **resolution_params)

# Link the activity to the resolution so regressions can find it.
if created:
latest_resolution_activity = (
Activity.objects.filter(group=group, type=activity_type.value)
.order_by("-datetime")
.first()
)
if latest_resolution_activity and not latest_resolution_activity.ident:
latest_resolution_activity.update(ident=resolution.id)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Activity Linking Fails on Updated Resolutions

The if created: condition incorrectly restricts linking a new Activity to its GroupResolution only when the resolution is newly created. When an existing GroupResolution is updated, the Activity.ident field remains unset, which breaks regression detection functionality.

Fix in Cursor Fix in Web

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think that should be okay


issue_resolved.send_robust(
organization_id=organization_id,
user=None,
Expand Down
25 changes: 25 additions & 0 deletions tests/sentry/integrations/tasks/test_sync_status_inbound.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from sentry.integrations.models import Integration
from sentry.integrations.models.organization_integration import OrganizationIntegration
from sentry.integrations.tasks.sync_status_inbound import sync_status_inbound
from sentry.models.activity import Activity
from sentry.models.group import Group, GroupStatus
from sentry.models.grouplink import GroupLink
from sentry.models.groupresolution import GroupResolution
Expand Down Expand Up @@ -240,6 +241,18 @@ def test_resolve_next_release(self, mock_get_resolve_sync_action: mock.MagicMock
self._assert_group_resolved(self.group.id)
self._assert_resolve_in_release_activity_created(in_next_release=True)

# Verify the activity is linked to GroupResolution via ident
resolution = GroupResolution.objects.get(group=self.group)
activity = (
Activity.objects.filter(
group=self.group, type=ActivityType.SET_RESOLVED_IN_RELEASE.value
)
.order_by("-datetime")
.first()
)
assert activity is not None
assert activity.ident == str(resolution.id)

@mock.patch.object(ExampleIntegration, "get_resolve_sync_action")
def test_resolve_current_release(self, mock_get_resolve_sync_action: mock.MagicMock) -> None:
mock_get_resolve_sync_action.return_value = ResolveSyncAction.RESOLVE
Expand Down Expand Up @@ -272,6 +285,18 @@ def test_resolve_current_release(self, mock_get_resolve_sync_action: mock.MagicM
self._assert_group_resolved(self.group.id)
self._assert_resolve_in_release_activity_created(in_next_release=False)

# Verify the activity is linked to GroupResolution via ident
resolution = GroupResolution.objects.get(group=self.group)
activity = (
Activity.objects.filter(
group=self.group, type=ActivityType.SET_RESOLVED_IN_RELEASE.value
)
.order_by("-datetime")
.first()
)
assert activity is not None
assert activity.ident == str(resolution.id)

@mock.patch.object(ExampleIntegration, "get_resolve_sync_action")
def test_resolve_no_releases(self, mock_get_resolve_sync_action: mock.MagicMock) -> None:
mock_get_resolve_sync_action.return_value = ResolveSyncAction.RESOLVE
Expand Down
Loading