Skip to content

✨ feat(gitlab): add issue sync outbound support#107216

Open
iamrajjoshi wants to merge 2 commits intomasterfrom
raj/gitlab-feat-par/status-sync-outbound
Open

✨ feat(gitlab): add issue sync outbound support#107216
iamrajjoshi wants to merge 2 commits intomasterfrom
raj/gitlab-feat-par/status-sync-outbound

Conversation

@iamrajjoshi
Copy link
Copy Markdown
Collaborator

Outbound status sync support. It also uses the async repo loading pattern as github.

Configuring a Repo

Screen.Recording.2026-01-28.at.8.35.29.PM.mov

Outbound Status Sync

Screen.Recording.2026-01-28.at.9.00.14.PM.mov

Legal Boilerplate

Look, I get it. The entity doing business as "Sentry" was incorporated in the State of Delaware in 2015 as Functional Software, Inc. and is gonna need some rights from me in order to utilize my contributions in this here PR. So here's the deal: I retain all rights, title and interest in and to my contributions, and by keeping this boilerplate intact I confirm that Sentry can use, modify, copy, and redistribute my contributions, under Sentry's choice of terms.

@iamrajjoshi iamrajjoshi self-assigned this Jan 29, 2026
@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Jan 29, 2026
@iamrajjoshi iamrajjoshi force-pushed the raj/gitlab-feat-par/status-sync-outbound branch from 760e657 to b4293d0 Compare January 30, 2026 03:40
@iamrajjoshi iamrajjoshi force-pushed the raj/gitlab-feat-par/status-sync-inbound branch from c582fc5 to 5790fac Compare January 30, 2026 03:42
@iamrajjoshi iamrajjoshi force-pushed the raj/gitlab-feat-par/status-sync-outbound branch from b4293d0 to 5458f2d Compare January 30, 2026 03:43
@getsantry
Copy link
Copy Markdown
Contributor

getsantry bot commented Feb 20, 2026

This pull request has gone three weeks without activity. In another week, I will close it.

But! If you comment or otherwise update it, I will reset the clock, and if you add the label WIP, I will leave it alone unless WIP is removed ... forever!


"A weed is but an unloved flower." ― Ella Wheeler Wilcox 🥀

@getsantry getsantry bot added the Stale label Feb 20, 2026
@iamrajjoshi iamrajjoshi force-pushed the raj/gitlab-feat-par/status-sync-inbound branch from 5790fac to 778b71d Compare February 24, 2026 02:37
@iamrajjoshi iamrajjoshi force-pushed the raj/gitlab-feat-par/status-sync-outbound branch from 5458f2d to c8dfe02 Compare February 24, 2026 02:40
@getsantry getsantry bot removed the Stale label Feb 24, 2026
@iamrajjoshi iamrajjoshi force-pushed the raj/gitlab-feat-par/status-sync-outbound branch from c8dfe02 to e5e81c2 Compare March 3, 2026 04:42
@iamrajjoshi iamrajjoshi force-pushed the raj/gitlab-feat-par/status-sync-inbound branch 5 times, most recently from 5afe7f2 to f492317 Compare March 19, 2026 00:11
@iamrajjoshi iamrajjoshi force-pushed the raj/gitlab-feat-par/status-sync-inbound branch from f492317 to aeb4885 Compare March 25, 2026 16:27
Base automatically changed from raj/gitlab-feat-par/status-sync-inbound to master March 31, 2026 17:25
@iamrajjoshi iamrajjoshi force-pushed the raj/gitlab-feat-par/status-sync-outbound branch from e5e81c2 to 430424c Compare April 3, 2026 16:50
Comment thread src/sentry/integrations/gitlab/tasks.py Outdated
Comment thread src/sentry/integrations/gitlab/integration.py
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 3, 2026

Backend Test Failures

Failures on 1ff6369 in this run:

tests/sentry/integrations/api/endpoints/test_organization_integration_details.py::OrganizationIntegrationDetailsPostTest::test_update_configlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/integrations/api/endpoints/test_organization_integration_details.py:63: in test_update_config
    with patch("sentry.integrations.gitlab.integration.update_all_project_webhooks"):
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1495: in __enter__
    original, local = self.get_original()
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1465: in get_original
    raise AttributeError(
E   AttributeError: <module 'sentry.integrations.gitlab.integration' from '/home/runner/work/sentry/sentry/src/sentry/integrations/gitlab/integration.py'> does not have the attribute 'update_all_project_webhooks'
tests/sentry/integrations/gitlab/test_integration.py::GitlabIssueSyncTest::test_update_organization_config_does_not_trigger_webhook_update_on_current_versionlog
[gw0] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/integrations/gitlab/test_integration.py:1230: in test_update_organization_config_does_not_trigger_webhook_update_on_current_version
    with patch(
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1495: in __enter__
    original, local = self.get_original()
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1465: in get_original
    raise AttributeError(
E   AttributeError: <module 'sentry.integrations.gitlab.integration' from '/home/runner/work/sentry/sentry/src/sentry/integrations/gitlab/integration.py'> does not have the attribute 'update_all_project_webhooks'
tests/sentry/integrations/gitlab/test_integration.py::GitlabIssueSyncTest::test_update_organization_config_preserves_existinglog
[gw0] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/integrations/gitlab/test_integration.py:904: in test_update_organization_config_preserves_existing
    with patch("sentry.integrations.gitlab.integration.update_all_project_webhooks"):
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1495: in __enter__
    original, local = self.get_original()
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1465: in get_original
    raise AttributeError(
E   AttributeError: <module 'sentry.integrations.gitlab.integration' from '/home/runner/work/sentry/sentry/src/sentry/integrations/gitlab/integration.py'> does not have the attribute 'update_all_project_webhooks'
tests/sentry/integrations/gitlab/test_integration.py::GitlabIssueSyncTest::test_update_organization_config_preserves_other_config_valueslog
[gw0] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/integrations/gitlab/test_integration.py:1357: in test_update_organization_config_preserves_other_config_values
    with patch("sentry.integrations.gitlab.integration.update_all_project_webhooks"):
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1495: in __enter__
    original, local = self.get_original()
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1465: in get_original
    raise AttributeError(
E   AttributeError: <module 'sentry.integrations.gitlab.integration' from '/home/runner/work/sentry/sentry/src/sentry/integrations/gitlab/integration.py'> does not have the attribute 'update_all_project_webhooks'
tests/sentry/integrations/gitlab/test_search.py::GitlabSearchTest::test_finds_project_resultslog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/integrations/gitlab/test_search.py:97: in test_finds_project_results
    assert resp.data == [
E   AssertionError: assert [{'label': 'G...ry2/sentry2'}] == [{'label': 'G...'value': '2'}]
E     
E     At index 0 diff: {'label': 'GetSentry / Sentry', 'value': 'getsentry/sentry'} != {'value': '1', 'label': 'GetSentry / Sentry'}
E     
E     Full diff:
E       [
E           {
E               'label': 'GetSentry / Sentry',
E     -         'value': '1',
E     +         'value': 'getsentry/sentry',
E           },
E           {
E               'label': 'GetSentry2 / Sentry2',
E     -         'value': '2',
E     +         'value': 'getsentry2/sentry2',
E           },
E       ]
tests/sentry/integrations/gitlab/test_search.py::GitlabSearchTest::test_finds_project_results_with_paginationlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/integrations/gitlab/test_search.py:144: in test_finds_project_results_with_pagination
    assert resp.data[0] == {"value": "1", "label": "GetSentry / Sentry"}
E   AssertionError: assert {'label': 'Ge...entry/sentry'} == {'label': 'Ge... 'value': '1'}
E     
E     Omitting 1 identical items, use -vv to show
E     Differing items:
E     {'value': 'getsentry/sentry'} != {'value': '1'}
E     
E     Full diff:
E       {
E           'label': 'GetSentry / Sentry',
E     -     'value': '1',
E     +     'value': 'getsentry/sentry',
E       }
tests/sentry/integrations/gitlab/test_integration.py::GitlabIssueSyncTest::test_update_organization_configlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/integrations/gitlab/test_integration.py:874: in test_update_organization_config
    with patch("sentry.integrations.gitlab.integration.update_all_project_webhooks"):
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1495: in __enter__
    original, local = self.get_original()
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1465: in get_original
    raise AttributeError(
E   AttributeError: <module 'sentry.integrations.gitlab.integration' from '/home/runner/work/sentry/sentry/src/sentry/integrations/gitlab/integration.py'> does not have the attribute 'update_all_project_webhooks'
tests/sentry/integrations/gitlab/test_integration.py::GitlabIssueSyncTest::test_update_organization_config_invalid_statuslog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/integrations/gitlab/test_integration.py:1432: in test_update_organization_config_invalid_status
    with patch("sentry.integrations.gitlab.integration.update_all_project_webhooks"):
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1495: in __enter__
    original, local = self.get_original()
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1465: in get_original
    raise AttributeError(
E   AttributeError: <module 'sentry.integrations.gitlab.integration' from '/home/runner/work/sentry/sentry/src/sentry/integrations/gitlab/integration.py'> does not have the attribute 'update_all_project_webhooks'
tests/sentry/integrations/gitlab/test_integration.py::GitlabIssueSyncTest::test_update_organization_config_missing_statuslog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/integrations/gitlab/test_integration.py:1455: in test_update_organization_config_missing_status
    with patch("sentry.integrations.gitlab.integration.update_all_project_webhooks"):
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1495: in __enter__
    original, local = self.get_original()
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1465: in get_original
    raise AttributeError(
E   AttributeError: <module 'sentry.integrations.gitlab.integration' from '/home/runner/work/sentry/sentry/src/sentry/integrations/gitlab/integration.py'> does not have the attribute 'update_all_project_webhooks'
tests/sentry/integrations/gitlab/test_integration.py::GitlabIssueSyncTest::test_update_organization_config_status_synclog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/integrations/gitlab/test_integration.py:1393: in test_update_organization_config_status_sync
    with patch("sentry.integrations.gitlab.integration.update_all_project_webhooks"):
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1495: in __enter__
    original, local = self.get_original()
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1465: in get_original
    raise AttributeError(
E   AttributeError: <module 'sentry.integrations.gitlab.integration' from '/home/runner/work/sentry/sentry/src/sentry/integrations/gitlab/integration.py'> does not have the attribute 'update_all_project_webhooks'
tests/sentry/integrations/gitlab/test_integration.py::GitlabIssueSyncTest::test_update_organization_config_triggers_task_when_version_missinglog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/integrations/gitlab/test_integration.py:1319: in test_update_organization_config_triggers_task_when_version_missing
    with patch(
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1495: in __enter__
    original, local = self.get_original()
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1465: in get_original
    raise AttributeError(
E   AttributeError: <module 'sentry.integrations.gitlab.integration' from '/home/runner/work/sentry/sentry/src/sentry/integrations/gitlab/integration.py'> does not have the attribute 'update_all_project_webhooks'
tests/sentry/integrations/gitlab/test_integration.py::GitlabIssueSyncTest::test_update_organization_config_triggers_webhook_update_on_missing_versionlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/integrations/gitlab/test_integration.py:1274: in test_update_organization_config_triggers_webhook_update_on_missing_version
    with patch(
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1495: in __enter__
    original, local = self.get_original()
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1465: in get_original
    raise AttributeError(
E   AttributeError: <module 'sentry.integrations.gitlab.integration' from '/home/runner/work/sentry/sentry/src/sentry/integrations/gitlab/integration.py'> does not have the attribute 'update_all_project_webhooks'
tests/sentry/integrations/gitlab/test_integration.py::GitlabIssueSyncTest::test_update_organization_config_triggers_webhook_update_on_outdated_versionlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/integrations/gitlab/test_integration.py:1184: in test_update_organization_config_triggers_webhook_update_on_outdated_version
    with patch(
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1495: in __enter__
    original, local = self.get_original()
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1465: in get_original
    raise AttributeError(
E   AttributeError: <module 'sentry.integrations.gitlab.integration' from '/home/runner/work/sentry/sentry/src/sentry/integrations/gitlab/integration.py'> does not have the attribute 'update_all_project_webhooks'

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 3, 2026

Backend Test Failures

Failures on e5ff13f in this run:

tests/sentry/integrations/gitlab/test_integration.py::GitlabIssueSyncTest::test_update_organization_config_triggers_task_when_version_missinglog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/integrations/gitlab/test_integration.py:1323: in test_update_organization_config_triggers_task_when_version_missing
    with patch(
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1495: in __enter__
    original, local = self.get_original()
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1465: in get_original
    raise AttributeError(
E   AttributeError: <module 'sentry.integrations.gitlab.integration' from '/home/runner/work/sentry/sentry/src/sentry/integrations/gitlab/integration.py'> does not have the attribute 'update_all_project_webhooks'
tests/sentry/integrations/gitlab/test_integration.py::GitlabIssueSyncTest::test_update_organization_config_triggers_webhook_update_on_missing_versionlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/integrations/gitlab/test_integration.py:1278: in test_update_organization_config_triggers_webhook_update_on_missing_version
    with patch(
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1495: in __enter__
    original, local = self.get_original()
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1465: in get_original
    raise AttributeError(
E   AttributeError: <module 'sentry.integrations.gitlab.integration' from '/home/runner/work/sentry/sentry/src/sentry/integrations/gitlab/integration.py'> does not have the attribute 'update_all_project_webhooks'
tests/sentry/integrations/gitlab/test_integration.py::GitlabIssueSyncTest::test_update_organization_config_triggers_webhook_update_on_outdated_versionlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/integrations/gitlab/test_integration.py:1188: in test_update_organization_config_triggers_webhook_update_on_outdated_version
    with patch(
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1495: in __enter__
    original, local = self.get_original()
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1465: in get_original
    raise AttributeError(
E   AttributeError: <module 'sentry.integrations.gitlab.integration' from '/home/runner/work/sentry/sentry/src/sentry/integrations/gitlab/integration.py'> does not have the attribute 'update_all_project_webhooks'
tests/sentry/integrations/gitlab/test_integration.py::GitlabIssueSyncTest::test_update_organization_config_does_not_trigger_webhook_update_on_current_versionlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/integrations/gitlab/test_integration.py:1234: in test_update_organization_config_does_not_trigger_webhook_update_on_current_version
    with patch(
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1495: in __enter__
    original, local = self.get_original()
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:1465: in get_original
    raise AttributeError(
E   AttributeError: <module 'sentry.integrations.gitlab.integration' from '/home/runner/work/sentry/sentry/src/sentry/integrations/gitlab/integration.py'> does not have the attribute 'update_all_project_webhooks'

@iamrajjoshi iamrajjoshi force-pushed the raj/gitlab-feat-par/status-sync-outbound branch from 9424c5b to 3f8cf58 Compare April 3, 2026 20:04
@iamrajjoshi iamrajjoshi marked this pull request as ready for review April 3, 2026 20:05
@iamrajjoshi iamrajjoshi requested review from a team as code owners April 3, 2026 20:05
Comment on lines +358 to +361
IntegrationExternalProject.objects.filter(
organization_integration_id=self.org_integration.id
).delete()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Bug: The update_organization_config method deletes existing project mappings before validating new data, causing data loss if validation fails, as the operation is not in a transaction.
Severity: HIGH

Suggested Fix

Wrap the delete and create operations within a transaction.atomic() block to ensure that the entire update is rolled back if any part of it fails. Additionally, move all validation logic to execute before any database write operations, such as the delete() call, to prevent unnecessary database changes on invalid input.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: src/sentry/integrations/gitlab/integration.py#L358-L361

Potential issue: The `update_organization_config` method in the GitLab integration
deletes all existing `IntegrationExternalProject` records before fully validating the
new configuration. Because this operation is not wrapped in a database transaction, if a
validation check fails after the deletion has occurred, the process aborts, resulting in
the permanent loss of all previously configured project mappings. This happens when a
user provides a configuration that passes initial checks but fails later validation,
such as providing an invalid status value like `"invalid_status"` for `on_resolve`.

Did we get this right? 👍 / 👎 to inform future reviews.

Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

Bugbot Autofix prepared fixes for both issues found in the latest run.

  • ✅ Fixed: Search value change breaks existing issue creation flow
    • Reverted search endpoint to return numeric project IDs instead of path_with_namespace to maintain backward compatibility with existing issue creation and linking flows.
  • ✅ Fixed: Status validation occurs after deleting existing records
    • Moved status value validation before the deletion of existing IntegrationExternalProject records to prevent data loss if validation fails.

Create PR

Or push these changes by commenting:

@cursor push b751f2f38c
Preview (b751f2f38c)
diff --git a/src/sentry/integrations/gitlab/integration.py b/src/sentry/integrations/gitlab/integration.py
--- a/src/sentry/integrations/gitlab/integration.py
+++ b/src/sentry/integrations/gitlab/integration.py
@@ -353,15 +353,9 @@
             ):
                 raise IntegrationError("Resolve and unresolve status are required.")
 
-            data["sync_status_forward"] = bool(project_mappings)
-
-            IntegrationExternalProject.objects.filter(
-                organization_integration_id=self.org_integration.id
-            ).delete()
-
+            # Validate status values before deleting existing records
+            valid_statuses = {GitLabIssueStatus.OPENED.value, GitLabIssueStatus.CLOSED.value}
             for project_path, statuses in project_mappings.items():
-                # Validate status values
-                valid_statuses = {GitLabIssueStatus.OPENED.value, GitLabIssueStatus.CLOSED.value}
                 if statuses["on_resolve"] not in valid_statuses:
                     raise IntegrationError(
                         f"Invalid resolve status: {statuses['on_resolve']}. Must be 'opened' or 'closed'."
@@ -371,6 +365,13 @@
                         f"Invalid unresolve status: {statuses['on_unresolve']}. Must be 'opened' or 'closed'."
                     )
 
+            data["sync_status_forward"] = bool(project_mappings)
+
+            IntegrationExternalProject.objects.filter(
+                organization_integration_id=self.org_integration.id
+            ).delete()
+
+            for project_path, statuses in project_mappings.items():
                 IntegrationExternalProject.objects.create(
                     organization_integration_id=self.org_integration.id,
                     external_id=project_path,

diff --git a/src/sentry/integrations/gitlab/search.py b/src/sentry/integrations/gitlab/search.py
--- a/src/sentry/integrations/gitlab/search.py
+++ b/src/sentry/integrations/gitlab/search.py
@@ -79,7 +79,7 @@
                 [
                     {
                         "label": project["name_with_namespace"],
-                        "value": project["path_with_namespace"],
+                        "value": project["id"],
                     }
                     for project in response
                 ]

This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

Comment thread src/sentry/integrations/gitlab/search.py
name=project_path,
resolved_status=statuses["on_resolve"],
unresolved_status=statuses["on_unresolve"],
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Status validation occurs after deleting existing records

Medium Severity

In update_organization_config, existing IntegrationExternalProject records are deleted on line 358–360 before the per-mapping status value validation runs inside the loop on lines 364–372. If an invalid status value (not "opened" or "closed") is submitted for any project mapping, the IntegrationError is raised after all existing records have already been permanently deleted, causing data loss of the previous configuration.

Fix in Cursor Fix in Web

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@iamrajjoshi reminder that we need to wrap these in transactions as a cleanup PR to ensure this isn't a problem.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Will follow up in a cleanup PR to wrap the delete+create in transaction.atomic().

name=project_path,
resolved_status=statuses["on_resolve"],
unresolved_status=statuses["on_unresolve"],
)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@iamrajjoshi reminder that we need to wrap these in transactions as a cleanup PR to ensure this isn't a problem.

Comment thread src/sentry/integrations/gitlab/search.py

# Verify task was NOT called
mock_task.delay.assert_not_called()
mock_task.assert_not_called()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Instead of mocking the service, should we continue to assert that the task is correctly queued? This presumes that the RPC call is correct instead of testing that the parameters we're passing are correct.

If this is tested elsewhere, can you update the mock names to correctly reflect the change please?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Renamed mock_taskmock_schedule_webhooks throughout — the variable was a leftover from when we mocked the Celery task directly. The RPC call tests do assert the correct org/integration args on the call sites that trigger it. Happy to discuss if you think we should go deeper and test at the task-queue level instead.

iamrajjoshi and others added 2 commits April 8, 2026 10:44
Propagate Sentry issue resolution and assignment to linked GitLab
issues. Includes sync_status_outbound and sync_assignee_outbound
implementations, status mapping via IntegrationExternalProject,
and a schedule_update_gitlab_project_webhooks RPC method.

Co-Authored-By: Claude <noreply@anthropic.com>
- URL-encode project_id in client.py to support path_with_namespace
  values (e.g. getsentry/sentry → getsentry%2Fsentry) when querying
  GitLab project issues API
- Rename mock_task → mock_schedule_webhooks in webhook update tests to
  accurately reflect that the RPC service method is being mocked, not
  a Celery task directly

Co-Authored-By: Claude <noreply@anthropic.com>
@iamrajjoshi iamrajjoshi force-pushed the raj/gitlab-feat-par/status-sync-outbound branch from f054e15 to c0b439e Compare April 8, 2026 17:45
@GabeVillalobos GabeVillalobos added the Trigger: getsentry tests Once code is reviewed: apply label to PR to trigger getsentry tests label Apr 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components Trigger: getsentry tests Once code is reviewed: apply label to PR to trigger getsentry tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants