Skip to content
Closed
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
27 changes: 6 additions & 21 deletions src/sentry/integrations/bitbucket/repository.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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"],
Expand All @@ -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"],
}

Expand Down
13 changes: 10 additions & 3 deletions tests/sentry/integrations/bitbucket/test_repository.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import datetime
from datetime import timezone
from functools import cached_property
from unittest import mock

import pytest
import responses
Expand Down Expand Up @@ -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(
Expand All @@ -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,
)

Expand All @@ -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):
Expand Down
Loading