feat(ecosystem): Implement cross-system issue synchronization#6
feat(ecosystem): Implement cross-system issue synchronization#6everettbu wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR implements cross-system issue synchronization by introducing an assignment source tracking mechanism to prevent sync cycles between integrations. When an assignment originates from an integration, the system can now identify the source and avoid syncing back to the same integration that initiated the change.
Key changes:
- Added
AssignmentSourceservice to track assignment origins with integration metadata - Modified assignment methods to accept and propagate assignment source information
- Updated sync logic to prevent cycles by checking if the sync target matches the assignment source
Reviewed Changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
src/sentry/integrations/services/assignment_source.py |
New service class for tracking assignment sources with integration metadata |
src/sentry/models/groupassignee.py |
Updated assign/deassign methods to accept assignment source parameter |
src/sentry/integrations/utils/sync.py |
Modified sync functions to pass assignment source and prevent sync cycles |
src/sentry/integrations/tasks/sync_assignee_outbound.py |
Updated task to handle assignment source data |
src/sentry/integrations/mixins/issues.py |
Enhanced should_sync method to check assignment source for cycle prevention |
tests/sentry/models/test_groupassignee.py |
Added test coverage for assignment source functionality |
tests/sentry/integrations/services/test_assignment_source.py |
Unit tests for the new AssignmentSource service |
| result = AssignmentSource.from_dict(data) | ||
| assert result is None | ||
|
|
||
| def test_from_dict_inalid_data(self): |
There was a problem hiding this comment.
Method name contains a typo: 'inalid' should be 'invalid'.
| def test_from_dict_inalid_data(self): | |
| def test_from_dict_invalid_data(self): |
| external_issue, | ||
| is_resolved, | ||
| project_id, | ||
| assignment_source: AssignmentSource | None = None, | ||
| **kwargs, | ||
| ): |
There was a problem hiding this comment.
The sync_status_outbound method signature is updated to include assignment_source parameter, but this appears to be an abstract method. All implementing classes will need to be updated to match this new signature, which could be a breaking change.
| external_issue, | |
| is_resolved, | |
| project_id, | |
| assignment_source: AssignmentSource | None = None, | |
| **kwargs, | |
| ): | |
| external_issue: ExternalIssue, | |
| is_resolved: bool, | |
| project_id: int, | |
| assignment_source: AssignmentSource | None = None, | |
| **kwargs: Any, | |
| ) -> None: |
| class AssignmentSource: | ||
| source_name: str | ||
| integration_id: int | ||
| queued: datetime = timezone.now() |
There was a problem hiding this comment.
Using timezone.now() as a default field value will set the same timestamp for all instances created at import time, not at instantiation time. This should be a factory function or set in post_init.
| queued: datetime = timezone.now() | |
| queued: datetime = field(default_factory=timezone.now) |
Test 7