Skip to content

fix(integrations): Disallow modifying a repo's integration#111739

Merged
cmanallen merged 3 commits intomasterfrom
cmanallen/disallow-repo-provider-change
Mar 27, 2026
Merged

fix(integrations): Disallow modifying a repo's integration#111739
cmanallen merged 3 commits intomasterfrom
cmanallen/disallow-repo-provider-change

Conversation

@cmanallen
Copy link
Copy Markdown
Member

No description provided.

@cmanallen cmanallen requested review from a team as code owners March 27, 2026 19:00
@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Mar 27, 2026
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 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Repository migration silently fails due to ignored integrationId
    • The repository details PUT endpoint now returns a 400 error when no valid updatable fields are provided, so integrationId-only migration requests no longer succeed silently.

Create PR

Or push these changes by commenting:

@cursor push 4d3895d645
Preview (4d3895d645)
diff --git a/src/sentry/integrations/api/endpoints/organization_repository_details.py b/src/sentry/integrations/api/endpoints/organization_repository_details.py
--- a/src/sentry/integrations/api/endpoints/organization_repository_details.py
+++ b/src/sentry/integrations/api/endpoints/organization_repository_details.py
@@ -81,28 +81,27 @@
                 update_kwargs["status"] = ObjectStatus.HIDDEN
             else:
                 raise NotImplementedError
-        if update_kwargs:
-            old_status = repo.status
-            with transaction.atomic(router.db_for_write(Repository)):
-                repo.update(**update_kwargs)
-                if (
-                    old_status == ObjectStatus.PENDING_DELETION
-                    and repo.status == ObjectStatus.ACTIVE
-                ):
-                    repo.reset_pending_deletion_field_names()
-                    repo.delete_pending_deletion_option()
-                elif repo.status == ObjectStatus.HIDDEN and old_status != repo.status:
-                    repository_cascade_delete_on_hide.apply_async(kwargs={"repo_id": repo.id})
+        if not update_kwargs:
+            return Response({"detail": "No valid update fields were provided"}, status=400)
 
-                    if repo.external_id and repo.provider:
-                        cleanup_seer_repository_preferences.apply_async(
-                            kwargs={
-                                "organization_id": repo.organization_id,
-                                "repo_external_id": repo.external_id,
-                                "repo_provider": repo.provider,
-                            }
-                        )
+        old_status = repo.status
+        with transaction.atomic(router.db_for_write(Repository)):
+            repo.update(**update_kwargs)
+            if old_status == ObjectStatus.PENDING_DELETION and repo.status == ObjectStatus.ACTIVE:
+                repo.reset_pending_deletion_field_names()
+                repo.delete_pending_deletion_option()
+            elif repo.status == ObjectStatus.HIDDEN and old_status != repo.status:
+                repository_cascade_delete_on_hide.apply_async(kwargs={"repo_id": repo.id})
 
+                if repo.external_id and repo.provider:
+                    cleanup_seer_repository_preferences.apply_async(
+                        kwargs={
+                            "organization_id": repo.organization_id,
+                            "repo_external_id": repo.external_id,
+                            "repo_provider": repo.provider,
+                        }
+                    )
+
         return Response(serialize(repo, request.user))
 
     def delete(self, request: Request, organization, repo_id) -> Response:

diff --git a/tests/sentry/integrations/api/endpoints/test_organization_repository_details.py b/tests/sentry/integrations/api/endpoints/test_organization_repository_details.py
--- a/tests/sentry/integrations/api/endpoints/test_organization_repository_details.py
+++ b/tests/sentry/integrations/api/endpoints/test_organization_repository_details.py
@@ -323,7 +323,7 @@
             }
         )
 
-    def test_put_does_not_change_provider(self) -> None:
+    def test_put_rejects_integration_id(self) -> None:
         self.login_as(user=self.user)
 
         org = self.create_organization(owner=self.user, name="baz")
@@ -339,9 +339,10 @@
         )
 
         url = reverse("sentry-api-0-organization-repository-details", args=[org.slug, repo.id])
-        response = self.client.put(url, data={"status": "visible", "integrationId": integration.id})
+        response = self.client.put(url, data={"integrationId": integration.id})
 
-        assert response.status_code == 200
+        assert response.status_code == 400
+        assert response.data["detail"] == "No valid update fields were provided"
 
         repo = Repository.objects.get(id=repo.id)
         assert repo.provider == "integrations:github"

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

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 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment thread src/sentry/integrations/api/endpoints/organization_repository_details.py Outdated
@cmanallen cmanallen enabled auto-merge (squash) March 27, 2026 19:40
@cmanallen cmanallen merged commit 81e7059 into master Mar 27, 2026
63 of 64 checks passed
@cmanallen cmanallen deleted the cmanallen/disallow-repo-provider-change branch March 27, 2026 19:47
geoffg-sentry added a commit that referenced this pull request Mar 27, 2026
front end change pending deploy of
#111739


originally added in #10008
@github-actions github-actions bot locked and limited conversation to collaborators Apr 12, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants