diff --git a/src/sentry/integrations/bitbucket/repository.py b/src/sentry/integrations/bitbucket/repository.py index e8e424f70193a1..690c9c9c0bcc88 100644 --- a/src/sentry/integrations/bitbucket/repository.py +++ b/src/sentry/integrations/bitbucket/repository.py @@ -1,6 +1,4 @@ -from sentry.locks import locks from sentry.models.apitoken import generate_token -from sentry.models.options.organization_option import OrganizationOption from sentry.organizations.services.organization.model import RpcOrganization from sentry.plugins.providers import IntegrationRepositoryProvider from sentry.shared_integrations.exceptions import ApiError @@ -24,27 +22,10 @@ def get_repository_data(self, organization, config): config["name"] = repo["full_name"] return config - def get_webhook_secret(self, organization): - # TODO(LB): Revisit whether Integrations V3 should be using OrganizationOption for storage - lock = locks.get( - f"bitbucket:webhook-secret:{organization.id}", - duration=60, - name="bitbucket_webhook_secret", - ) - with lock.acquire(): - secret = OrganizationOption.objects.get_value( - organization=organization, key="bitbucket:webhook_secret" - ) - if secret is None: - secret = generate_token() - OrganizationOption.objects.set_value( - organization=organization, key="bitbucket:webhook_secret", value=secret - ) - return secret - def build_repository_config(self, organization: RpcOrganization, data): installation = self.get_installation(data.get("installation"), organization.id) client = installation.get_client() + secret = generate_token() try: resp = client.create_hook( data["identifier"], @@ -54,17 +35,21 @@ def build_repository_config(self, organization: RpcOrganization, data): f"/extensions/bitbucket/organizations/{organization.id}/webhook/" ), "active": True, + "secret": secret, "events": ["repo:push", "pullrequest:fulfilled"], }, ) except Exception as e: installation.raise_error(e) else: + config = {"name": data["name"], "webhook_id": resp["uuid"]} + if resp.get("secret_set"): + config["webhook_secret"] = secret return { "name": data["identifier"], "external_id": data["external_id"], "url": "https://bitbucket.org/{}".format(data["name"]), - "config": {"name": data["name"], "webhook_id": resp["uuid"]}, + "config": config, "integration_id": data["installation"], } diff --git a/tests/sentry/integrations/bitbucket/test_repository.py b/tests/sentry/integrations/bitbucket/test_repository.py index 0e6f656573a9a5..ccb75a34c03515 100644 --- a/tests/sentry/integrations/bitbucket/test_repository.py +++ b/tests/sentry/integrations/bitbucket/test_repository.py @@ -1,6 +1,7 @@ import datetime from datetime import timezone from functools import cached_property +from unittest import mock import pytest import responses @@ -81,7 +82,8 @@ def test_compare_commits(self): ] @responses.activate - def test_build_repository_config(self): + @mock.patch("sentry.integrations.bitbucket.repository.generate_token", return_value="0" * 64) + def test_build_repository_config(self, mock_generate_token): full_repo_name = "laurynsentry/helloworld" webhook_id = "web-hook-id" responses.add( @@ -92,7 +94,7 @@ def test_build_repository_config(self): responses.add( responses.POST, "https://api.bitbucket.org/2.0/repositories/%s/hooks" % full_repo_name, - json={"uuid": webhook_id}, + json={"uuid": webhook_id, "secret_set": True}, status=201, ) @@ -119,13 +121,18 @@ def test_build_repository_config(self): "name": full_repo_name, } data = self.provider.build_repository_config(organization, data) + assert mock_generate_token.called assert data == { "name": full_repo_name, "external_id": REPO["uuid"], "url": "https://bitbucket.org/laurynsentry/helloworld", "integration_id": integration.id, - "config": {"name": full_repo_name, "webhook_id": webhook_id}, + "config": { + "name": full_repo_name, + "webhook_id": webhook_id, + "webhook_secret": "0" * 64, + }, } def test_repository_external_slug(self):