mirror of
https://github.com/hanzoai/sentinel.git
synced 2026-09-29 22:34:33 +00:00
795 lines
29 KiB
Python
795 lines
29 KiB
Python
from datetime import datetime, timedelta, timezone
|
|
from unittest.mock import patch
|
|
from uuid import uuid4
|
|
|
|
import responses
|
|
|
|
from fixtures.github import (
|
|
INSTALLATION_API_RESPONSE,
|
|
INSTALLATION_DELETE_EVENT_EXAMPLE,
|
|
INSTALLATION_EVENT_EXAMPLE,
|
|
PULL_REQUEST_CLOSED_EVENT_EXAMPLE,
|
|
PULL_REQUEST_EDITED_EVENT_EXAMPLE,
|
|
PULL_REQUEST_OPENED_EVENT_EXAMPLE,
|
|
PUSH_EVENT_EXAMPLE_INSTALLATION,
|
|
)
|
|
from sentry import options
|
|
from sentry.constants import ObjectStatus
|
|
from sentry.middleware.integrations.parsers.github import GithubRequestParser
|
|
from sentry.models.commit import Commit
|
|
from sentry.models.commitauthor import CommitAuthor
|
|
from sentry.models.commitfilechange import CommitFileChange
|
|
from sentry.models.grouplink import GroupLink
|
|
from sentry.models.integrations.integration import Integration
|
|
from sentry.models.integrations.organization_integration import OrganizationIntegration
|
|
from sentry.models.pullrequest import PullRequest
|
|
from sentry.models.repository import Repository
|
|
from sentry.silo import SiloMode
|
|
from sentry.testutils.cases import APITestCase
|
|
from sentry.testutils.helpers.features import with_feature
|
|
from sentry.testutils.silo import assume_test_silo_mode, control_silo_test, region_silo_test
|
|
|
|
|
|
@region_silo_test
|
|
class WebhookTest(APITestCase):
|
|
def setUp(self):
|
|
self.url = "/extensions/github/webhook/"
|
|
self.secret = "b3002c3e321d4b7880360d397db2ccfd"
|
|
options.set("github-app.webhook-secret", self.secret)
|
|
|
|
def test_get(self):
|
|
response = self.client.get(self.url)
|
|
|
|
assert response.status_code == 405
|
|
|
|
def test_unregistered_event(self):
|
|
project = self.project # noqa force creation
|
|
|
|
response = self.client.post(
|
|
path=self.url,
|
|
data=PUSH_EVENT_EXAMPLE_INSTALLATION,
|
|
content_type="application/json",
|
|
HTTP_X_GITHUB_EVENT="UnregisteredEvent",
|
|
HTTP_X_HUB_SIGNATURE="sha1=2b116e7c1f7510b62727673b0f9acc0db951263a",
|
|
HTTP_X_GITHUB_DELIVERY=str(uuid4()),
|
|
)
|
|
|
|
assert response.status_code == 204
|
|
|
|
def test_invalid_signature_event(self):
|
|
response = self.client.post(
|
|
path=self.url,
|
|
data=PUSH_EVENT_EXAMPLE_INSTALLATION,
|
|
content_type="application/json",
|
|
HTTP_X_GITHUB_EVENT="push",
|
|
HTTP_X_HUB_SIGNATURE="sha1=33521abeaaf9a57c2abf486e0ccd54d23cf36fec",
|
|
HTTP_X_GITHUB_DELIVERY=str(uuid4()),
|
|
)
|
|
|
|
assert response.status_code == 401
|
|
|
|
|
|
@control_silo_test
|
|
class InstallationEventWebhookTest(APITestCase):
|
|
base_url = "https://api.github.com"
|
|
|
|
def setUp(self):
|
|
self.url = "/extensions/github/webhook/"
|
|
self.secret = "b3002c3e321d4b7880360d397db2ccfd"
|
|
options.set("github-app.webhook-secret", self.secret)
|
|
|
|
@responses.activate
|
|
@patch("sentry.integrations.github.client.get_jwt", return_value=b"jwt_token_1")
|
|
def test_installation_created(self, get_jwt):
|
|
responses.add(
|
|
method=responses.GET,
|
|
url="https://api.github.com/app/installations/2",
|
|
body=INSTALLATION_API_RESPONSE,
|
|
status=200,
|
|
content_type="application/json",
|
|
)
|
|
|
|
response = self.client.post(
|
|
path=self.url,
|
|
data=INSTALLATION_EVENT_EXAMPLE,
|
|
content_type="application/json",
|
|
HTTP_X_GITHUB_EVENT="installation",
|
|
HTTP_X_HUB_SIGNATURE="sha1=348e46312df2901e8cb945616ee84ce30d9987c9",
|
|
HTTP_X_GITHUB_DELIVERY=str(uuid4()),
|
|
)
|
|
assert response.status_code == 204
|
|
|
|
integration = Integration.objects.get(external_id=2)
|
|
assert integration.external_id == "2"
|
|
assert integration.name == "octocat"
|
|
assert integration.metadata["sender"]["id"] == 1
|
|
assert integration.metadata["sender"]["login"] == "octocat"
|
|
assert integration.status == ObjectStatus.ACTIVE
|
|
|
|
|
|
@control_silo_test
|
|
class InstallationDeleteEventWebhookTest(APITestCase):
|
|
base_url = "https://api.github.com"
|
|
|
|
def setUp(self):
|
|
self.url = "/extensions/github/webhook/"
|
|
self.secret = "b3002c3e321d4b7880360d397db2ccfd"
|
|
options.set("github-app.webhook-secret", self.secret)
|
|
|
|
@patch("sentry.integrations.github.client.get_jwt", return_value=b"jwt_token_1")
|
|
def test_installation_deleted(self, get_jwt):
|
|
project = self.project # force creation
|
|
|
|
future_expires = datetime.now().replace(microsecond=0) + timedelta(minutes=5)
|
|
integration = self.create_integration(
|
|
name="octocat",
|
|
organization=self.organization,
|
|
external_id="2",
|
|
provider="github",
|
|
metadata={"access_token": "1234", "expires_at": future_expires.isoformat()},
|
|
)
|
|
integration.add_organization(project.organization.id, self.user)
|
|
assert integration.status == ObjectStatus.ACTIVE
|
|
|
|
repo = self.create_repo(
|
|
project,
|
|
provider="integrations:github",
|
|
integration_id=integration.id,
|
|
)
|
|
|
|
with patch.object(GithubRequestParser, "get_regions_from_organizations", return_value=[]):
|
|
response = self.client.post(
|
|
path=self.url,
|
|
data=INSTALLATION_DELETE_EVENT_EXAMPLE,
|
|
content_type="application/json",
|
|
HTTP_X_GITHUB_EVENT="installation",
|
|
HTTP_X_HUB_SIGNATURE="sha1=8f73a86cf0a0cfa6d05626ce425cef5d3c4062aa",
|
|
HTTP_X_GITHUB_DELIVERY=str(uuid4()),
|
|
)
|
|
assert response.status_code == 204
|
|
|
|
integration = Integration.objects.get(external_id=2)
|
|
assert integration.external_id == "2"
|
|
assert integration.name == "octocat"
|
|
assert integration.status == ObjectStatus.DISABLED
|
|
|
|
with assume_test_silo_mode(SiloMode.REGION):
|
|
repo.refresh_from_db()
|
|
assert repo.status == ObjectStatus.DISABLED
|
|
|
|
@patch("sentry.integrations.github.client.get_jwt", return_value=b"jwt_token_1")
|
|
def test_installation_deleted_no_org_integration(self, get_jwt):
|
|
project = self.project # force creation
|
|
|
|
future_expires = datetime.now().replace(microsecond=0) + timedelta(minutes=5)
|
|
integration = self.create_integration(
|
|
name="octocat",
|
|
organization=self.organization,
|
|
external_id="2",
|
|
provider="github",
|
|
metadata={"access_token": "1234", "expires_at": future_expires.isoformat()},
|
|
)
|
|
integration.add_organization(project.organization.id, self.user)
|
|
assert integration.status == ObjectStatus.ACTIVE
|
|
|
|
# Set up condition that the OrganizationIntegration is deleted prior to the webhook event
|
|
OrganizationIntegration.objects.filter(
|
|
integration_id=integration.id,
|
|
organization_id=self.organization.id,
|
|
).delete()
|
|
|
|
response = self.client.post(
|
|
path=self.url,
|
|
data=INSTALLATION_DELETE_EVENT_EXAMPLE,
|
|
content_type="application/json",
|
|
HTTP_X_GITHUB_EVENT="installation",
|
|
HTTP_X_HUB_SIGNATURE="sha1=8f73a86cf0a0cfa6d05626ce425cef5d3c4062aa",
|
|
HTTP_X_GITHUB_DELIVERY=str(uuid4()),
|
|
)
|
|
assert response.status_code == 204
|
|
|
|
integration = Integration.objects.get(external_id=2)
|
|
assert integration.external_id == "2"
|
|
assert integration.name == "octocat"
|
|
assert integration.status == ObjectStatus.DISABLED
|
|
|
|
|
|
@region_silo_test
|
|
class PushEventWebhookTest(APITestCase):
|
|
def setUp(self):
|
|
self.url = "/extensions/github/webhook/"
|
|
self.secret = "b3002c3e321d4b7880360d397db2ccfd"
|
|
options.set("github-app.webhook-secret", self.secret)
|
|
|
|
def _setup_repo_test(self, project):
|
|
future_expires = datetime.now().replace(microsecond=0) + timedelta(minutes=5)
|
|
with assume_test_silo_mode(SiloMode.CONTROL):
|
|
integration = self.create_integration(
|
|
organization=self.organization,
|
|
external_id="12345",
|
|
provider="github",
|
|
metadata={"access_token": "1234", "expires_at": future_expires.isoformat()},
|
|
)
|
|
integration.add_organization(project.organization.id, self.user)
|
|
|
|
response = self.client.post(
|
|
path=self.url,
|
|
data=PUSH_EVENT_EXAMPLE_INSTALLATION,
|
|
content_type="application/json",
|
|
HTTP_X_GITHUB_EVENT="push",
|
|
HTTP_X_HUB_SIGNATURE="sha1=2b116e7c1f7510b62727673b0f9acc0db951263a",
|
|
HTTP_X_GITHUB_DELIVERY=str(uuid4()),
|
|
)
|
|
|
|
assert response.status_code == 204
|
|
|
|
def test_simple(self):
|
|
project = self.project # force creation
|
|
|
|
repo = Repository.objects.create(
|
|
organization_id=project.organization.id,
|
|
external_id="35129377",
|
|
provider="integrations:github",
|
|
name="baxterthehacker/public-repo",
|
|
)
|
|
|
|
self._setup_repo_test(project)
|
|
|
|
commit_list = list(
|
|
Commit.objects.filter(
|
|
# organization_id=project.organization_id,
|
|
)
|
|
.select_related("author")
|
|
.order_by("-date_added")
|
|
)
|
|
|
|
assert len(commit_list) == 2
|
|
|
|
commit = commit_list[0]
|
|
|
|
assert commit.key == "133d60480286590a610a0eb7352ff6e02b9674c4"
|
|
assert commit.message == "Update hello.py"
|
|
assert commit.author.name == "bàxterthehacker"
|
|
assert commit.author.email == "[email protected]"
|
|
assert commit.author.external_id is None
|
|
assert commit.date_added == datetime(2015, 5, 5, 23, 45, 15, tzinfo=timezone.utc)
|
|
|
|
commit = commit_list[1]
|
|
|
|
assert commit.key == "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c"
|
|
assert commit.message == "Update README.md"
|
|
assert commit.author.name == "bàxterthehacker"
|
|
assert commit.author.email == "[email protected]"
|
|
assert commit.author.external_id is None
|
|
assert commit.date_added == datetime(2015, 5, 5, 23, 40, 15, tzinfo=timezone.utc)
|
|
|
|
commit_filechanges = CommitFileChange.objects.all()
|
|
assert len(commit_filechanges) == 4
|
|
|
|
repo.refresh_from_db()
|
|
assert set(repo.languages) == {"python", "javascript"}
|
|
|
|
@patch("sentry.integrations.github.webhook.metrics")
|
|
def test_creates_missing_repo(self, mock_metrics):
|
|
project = self.project # force creation
|
|
|
|
self._setup_repo_test(project)
|
|
|
|
repos = Repository.objects.all()
|
|
assert len(repos) == 1
|
|
assert repos[0].organization_id == project.organization.id
|
|
assert repos[0].external_id == "35129377"
|
|
assert repos[0].provider == "integrations:github"
|
|
assert repos[0].name == "baxterthehacker/public-repo"
|
|
mock_metrics.incr.assert_called_with("github.webhook.repository_created")
|
|
|
|
def test_ignores_hidden_repo(self):
|
|
project = self.project # force creation
|
|
|
|
repo = self.create_repo(
|
|
project=project,
|
|
provider="integrations:github",
|
|
name="baxterthehacker/public-repo",
|
|
)
|
|
repo.status = ObjectStatus.HIDDEN
|
|
repo.external_id = "35129377"
|
|
repo.save()
|
|
|
|
self._setup_repo_test(project)
|
|
|
|
repos = Repository.objects.all()
|
|
assert len(repos) == 1
|
|
assert repos[0] == repo
|
|
|
|
def test_anonymous_lookup(self):
|
|
project = self.project # force creation
|
|
|
|
repo = Repository.objects.create(
|
|
organization_id=project.organization.id,
|
|
external_id="35129377",
|
|
provider="integrations:github",
|
|
name="baxterthehacker/public-repo",
|
|
)
|
|
|
|
CommitAuthor.objects.create(
|
|
external_id="github:baxterthehacker",
|
|
organization_id=project.organization_id,
|
|
email="[email protected]",
|
|
name="bàxterthehacker",
|
|
)
|
|
|
|
self._setup_repo_test(project)
|
|
|
|
commit_list = list(
|
|
Commit.objects.filter(organization_id=project.organization_id)
|
|
.select_related("author")
|
|
.order_by("-date_added")
|
|
)
|
|
|
|
# should be skipping the #skipsentry commit
|
|
assert len(commit_list) == 2
|
|
|
|
commit = commit_list[0]
|
|
|
|
assert commit.key == "133d60480286590a610a0eb7352ff6e02b9674c4"
|
|
assert commit.message == "Update hello.py"
|
|
assert commit.author.name == "bàxterthehacker"
|
|
assert commit.author.email == "[email protected]"
|
|
assert commit.date_added == datetime(2015, 5, 5, 23, 45, 15, tzinfo=timezone.utc)
|
|
|
|
commit = commit_list[1]
|
|
|
|
assert commit.key == "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c"
|
|
assert commit.message == "Update README.md"
|
|
assert commit.author.name == "bàxterthehacker"
|
|
assert commit.author.email == "[email protected]"
|
|
assert commit.date_added == datetime(2015, 5, 5, 23, 40, 15, tzinfo=timezone.utc)
|
|
|
|
commit_filechanges = CommitFileChange.objects.all()
|
|
assert len(commit_filechanges) == 4
|
|
|
|
repo.refresh_from_db()
|
|
assert set(repo.languages) == {"python", "javascript"}
|
|
|
|
def test_multiple_orgs(self):
|
|
project = self.project # force creation
|
|
|
|
Repository.objects.create(
|
|
organization_id=project.organization.id,
|
|
external_id="35129377",
|
|
provider="integrations:github",
|
|
name="baxterthehacker/public-repo",
|
|
)
|
|
|
|
future_expires = datetime.now().replace(microsecond=0) + timedelta(minutes=5)
|
|
with assume_test_silo_mode(SiloMode.CONTROL):
|
|
integration = self.create_integration(
|
|
organization=self.organization,
|
|
external_id="12345",
|
|
provider="github",
|
|
metadata={"access_token": "1234", "expires_at": future_expires.isoformat()},
|
|
)
|
|
integration.add_organization(project.organization.id, self.user)
|
|
|
|
org2 = self.create_organization()
|
|
project2 = self.create_project(organization=org2, name="bar")
|
|
|
|
self.create_repo(
|
|
project=project2,
|
|
provider="integrations:github",
|
|
name="another/repo",
|
|
)
|
|
|
|
future_expires = datetime.now().replace(microsecond=0) + timedelta(minutes=5)
|
|
with assume_test_silo_mode(SiloMode.CONTROL):
|
|
integration = self.create_integration(
|
|
organization=self.organization,
|
|
external_id="99",
|
|
provider="github",
|
|
metadata={"access_token": "1234", "expires_at": future_expires.isoformat()},
|
|
)
|
|
integration.add_organization(org2.id, self.user)
|
|
|
|
response = self.client.post(
|
|
path=self.url,
|
|
data=PUSH_EVENT_EXAMPLE_INSTALLATION,
|
|
content_type="application/json",
|
|
HTTP_X_GITHUB_EVENT="push",
|
|
HTTP_X_HUB_SIGNATURE="sha1=2b116e7c1f7510b62727673b0f9acc0db951263a",
|
|
HTTP_X_GITHUB_DELIVERY=str(uuid4()),
|
|
)
|
|
|
|
assert response.status_code == 204
|
|
|
|
commit_list = list(
|
|
Commit.objects.filter(organization_id=project.organization_id)
|
|
.select_related("author")
|
|
.order_by("-date_added")
|
|
)
|
|
|
|
assert len(commit_list) == 2
|
|
|
|
commit_list = list(
|
|
Commit.objects.filter(organization_id=org2.id)
|
|
.select_related("author")
|
|
.order_by("-date_added")
|
|
)
|
|
assert len(commit_list) == 0
|
|
|
|
@patch("sentry.integrations.github.webhook.metrics")
|
|
def test_multiple_orgs_creates_missing_repos(self, mock_metrics):
|
|
project = self.project # force creation
|
|
|
|
org2 = self.create_organization()
|
|
|
|
future_expires = datetime.now().replace(microsecond=0) + timedelta(minutes=5)
|
|
with assume_test_silo_mode(SiloMode.CONTROL):
|
|
integration = self.create_integration(
|
|
organization=self.organization,
|
|
external_id="12345",
|
|
provider="github",
|
|
metadata={"access_token": "1234", "expires_at": future_expires.isoformat()},
|
|
)
|
|
integration.add_organization(project.organization.id, self.user)
|
|
integration.add_organization(org2.id, self.user)
|
|
|
|
response = self.client.post(
|
|
path=self.url,
|
|
data=PUSH_EVENT_EXAMPLE_INSTALLATION,
|
|
content_type="application/json",
|
|
HTTP_X_GITHUB_EVENT="push",
|
|
HTTP_X_HUB_SIGNATURE="sha1=2b116e7c1f7510b62727673b0f9acc0db951263a",
|
|
HTTP_X_GITHUB_DELIVERY=str(uuid4()),
|
|
)
|
|
|
|
assert response.status_code == 204
|
|
|
|
repos = Repository.objects.all().order_by("date_added")
|
|
assert len(repos) == 2
|
|
|
|
assert repos[0].organization_id == project.organization.id
|
|
assert repos[1].organization_id == org2.id
|
|
for repo in repos:
|
|
assert repo.external_id == "35129377"
|
|
assert repo.provider == "integrations:github"
|
|
assert repo.name == "baxterthehacker/public-repo"
|
|
mock_metrics.incr.assert_called_with("github.webhook.repository_created")
|
|
|
|
def test_multiple_orgs_ignores_hidden_repo(self):
|
|
project = self.project # force creation
|
|
|
|
org2 = self.create_organization()
|
|
|
|
future_expires = datetime.now().replace(microsecond=0) + timedelta(minutes=5)
|
|
with assume_test_silo_mode(SiloMode.CONTROL):
|
|
integration = self.create_integration(
|
|
organization=self.organization,
|
|
external_id="12345",
|
|
provider="github",
|
|
metadata={"access_token": "1234", "expires_at": future_expires.isoformat()},
|
|
)
|
|
integration.add_organization(project.organization.id, self.user)
|
|
integration.add_organization(org2.id, self.user)
|
|
|
|
repo = self.create_repo(
|
|
project=project,
|
|
provider="integrations:github",
|
|
name="baxterthehacker/public-repo",
|
|
)
|
|
repo.external_id = "35129377"
|
|
repo.status = ObjectStatus.HIDDEN
|
|
repo.save()
|
|
|
|
response = self.client.post(
|
|
path=self.url,
|
|
data=PUSH_EVENT_EXAMPLE_INSTALLATION,
|
|
content_type="application/json",
|
|
HTTP_X_GITHUB_EVENT="push",
|
|
HTTP_X_HUB_SIGNATURE="sha1=2b116e7c1f7510b62727673b0f9acc0db951263a",
|
|
HTTP_X_GITHUB_DELIVERY=str(uuid4()),
|
|
)
|
|
|
|
assert response.status_code == 204
|
|
|
|
repos = Repository.objects.all()
|
|
assert len(repos) == 1
|
|
|
|
assert repos[0] == repo
|
|
|
|
|
|
@region_silo_test
|
|
class PullRequestEventWebhook(APITestCase):
|
|
def setUp(self):
|
|
self.url = "/extensions/github/webhook/"
|
|
self.secret = "b3002c3e321d4b7880360d397db2ccfd"
|
|
options.set("github-app.webhook-secret", self.secret)
|
|
|
|
def _setup_repo_test(self, project):
|
|
future_expires = datetime.now().replace(microsecond=0) + timedelta(minutes=5)
|
|
with assume_test_silo_mode(SiloMode.CONTROL):
|
|
integration = self.create_integration(
|
|
organization=self.organization,
|
|
external_id="12345",
|
|
provider="github",
|
|
metadata={"access_token": "1234", "expires_at": future_expires.isoformat()},
|
|
)
|
|
integration.add_organization(project.organization.id, self.user)
|
|
|
|
response = self.client.post(
|
|
path=self.url,
|
|
data=PULL_REQUEST_OPENED_EVENT_EXAMPLE,
|
|
content_type="application/json",
|
|
HTTP_X_GITHUB_EVENT="pull_request",
|
|
HTTP_X_HUB_SIGNATURE="sha1=bc7ce12fc1058a35bf99355e6fc0e6da72c35de3",
|
|
HTTP_X_GITHUB_DELIVERY=str(uuid4()),
|
|
)
|
|
|
|
assert response.status_code == 204
|
|
|
|
@with_feature("organizations:integrations-open-pr-comment")
|
|
@patch("sentry.integrations.github.webhook.metrics")
|
|
def test_opened(self, mock_metrics):
|
|
project = self.project # force creation
|
|
group = self.create_group(project=project, short_id=7)
|
|
|
|
repo = Repository.objects.create(
|
|
organization_id=project.organization.id,
|
|
external_id="35129377",
|
|
provider="integrations:github",
|
|
name="baxterthehacker/public-repo",
|
|
)
|
|
|
|
self._setup_repo_test(project)
|
|
|
|
prs = PullRequest.objects.filter(
|
|
repository_id=repo.id, organization_id=project.organization.id
|
|
)
|
|
|
|
assert len(prs) == 1
|
|
|
|
pr = prs[0]
|
|
|
|
assert pr.key == "1"
|
|
assert (
|
|
pr.message
|
|
== "This is a pretty simple change that we need to pull into master. Fixes BAR-7"
|
|
)
|
|
assert pr.title == "Update the README with new information"
|
|
assert pr.author.name == "baxterthehacker"
|
|
|
|
self.assert_group_link(group, pr)
|
|
|
|
mock_metrics.incr.assert_called_with("github.open_pr_comment.queue_task")
|
|
|
|
@patch("sentry.integrations.github.webhook.metrics")
|
|
def test_opened_missing_feature_flag(self, mock_metrics):
|
|
project = self.project # force creation
|
|
self.create_group(project=project, short_id=7)
|
|
|
|
Repository.objects.create(
|
|
organization_id=project.organization.id,
|
|
external_id="35129377",
|
|
provider="integrations:github",
|
|
name="baxterthehacker/public-repo",
|
|
)
|
|
|
|
self._setup_repo_test(project)
|
|
|
|
assert mock_metrics.incr.call_count == 0
|
|
|
|
@patch("sentry.integrations.github.webhook.metrics")
|
|
def test_creates_missing_repo(self, mock_metrics):
|
|
project = self.project # force creation
|
|
self._setup_repo_test(project)
|
|
|
|
repos = Repository.objects.all()
|
|
assert len(repos) == 1
|
|
assert repos[0].organization_id == project.organization.id
|
|
assert repos[0].external_id == "35129377"
|
|
assert repos[0].provider == "integrations:github"
|
|
assert repos[0].name == "baxterthehacker/public-repo"
|
|
mock_metrics.incr.assert_called_with("github.webhook.repository_created")
|
|
|
|
def test_ignores_hidden_repo(self):
|
|
project = self.project # force creation
|
|
|
|
repo = self.create_repo(
|
|
project=project,
|
|
provider="integrations:github",
|
|
name="baxterthehacker/public-repo",
|
|
)
|
|
repo.status = ObjectStatus.HIDDEN
|
|
repo.external_id = "35129377"
|
|
repo.save()
|
|
|
|
self._setup_repo_test(project)
|
|
|
|
repos = Repository.objects.all()
|
|
assert len(repos) == 1
|
|
assert repos[0] == repo
|
|
|
|
@patch("sentry.integrations.github.webhook.metrics")
|
|
def test_multiple_orgs_creates_missing_repo(self, mock_metrics):
|
|
project = self.project # force creation
|
|
|
|
org2 = self.create_organization()
|
|
|
|
future_expires = datetime.now().replace(microsecond=0) + timedelta(minutes=5)
|
|
with assume_test_silo_mode(SiloMode.CONTROL):
|
|
integration = self.create_integration(
|
|
organization=self.organization,
|
|
external_id="12345",
|
|
provider="github",
|
|
metadata={"access_token": "1234", "expires_at": future_expires.isoformat()},
|
|
)
|
|
integration.add_organization(project.organization.id, self.user)
|
|
integration.add_organization(org2.id, self.user)
|
|
|
|
response = self.client.post(
|
|
path=self.url,
|
|
data=PULL_REQUEST_OPENED_EVENT_EXAMPLE,
|
|
content_type="application/json",
|
|
HTTP_X_GITHUB_EVENT="pull_request",
|
|
HTTP_X_HUB_SIGNATURE="sha1=bc7ce12fc1058a35bf99355e6fc0e6da72c35de3",
|
|
HTTP_X_GITHUB_DELIVERY=str(uuid4()),
|
|
)
|
|
|
|
assert response.status_code == 204
|
|
|
|
repos = Repository.objects.all()
|
|
assert len(repos) == 2
|
|
|
|
assert repos[0].organization_id == project.organization.id
|
|
assert repos[1].organization_id == org2.id
|
|
for repo in repos:
|
|
assert repo.external_id == "35129377"
|
|
assert repo.provider == "integrations:github"
|
|
assert repo.name == "baxterthehacker/public-repo"
|
|
mock_metrics.incr.assert_called_with("github.webhook.repository_created")
|
|
|
|
def test_multiple_orgs_ignores_hidden_repo(self):
|
|
project = self.project # force creation
|
|
|
|
org2 = self.create_organization()
|
|
|
|
future_expires = datetime.now().replace(microsecond=0) + timedelta(minutes=5)
|
|
with assume_test_silo_mode(SiloMode.CONTROL):
|
|
integration = self.create_integration(
|
|
organization=self.organization,
|
|
external_id="12345",
|
|
provider="github",
|
|
metadata={"access_token": "1234", "expires_at": future_expires.isoformat()},
|
|
)
|
|
integration.add_organization(project.organization.id, self.user)
|
|
integration.add_organization(org2.id, self.user)
|
|
|
|
repo = self.create_repo(
|
|
project=project,
|
|
provider="integrations:github",
|
|
name="baxterthehacker/public-repo",
|
|
)
|
|
repo.external_id = "35129377"
|
|
repo.status = ObjectStatus.HIDDEN
|
|
repo.save()
|
|
|
|
response = self.client.post(
|
|
path=self.url,
|
|
data=PULL_REQUEST_OPENED_EVENT_EXAMPLE,
|
|
content_type="application/json",
|
|
HTTP_X_GITHUB_EVENT="pull_request",
|
|
HTTP_X_HUB_SIGNATURE="sha1=bc7ce12fc1058a35bf99355e6fc0e6da72c35de3",
|
|
HTTP_X_GITHUB_DELIVERY=str(uuid4()),
|
|
)
|
|
|
|
assert response.status_code == 204
|
|
|
|
repos = Repository.objects.all()
|
|
assert len(repos) == 1
|
|
|
|
assert repos[0] == repo
|
|
|
|
def test_edited(self):
|
|
project = self.project # force creation
|
|
group = self.create_group(project=project, short_id=7)
|
|
|
|
url = "/extensions/github/webhook/"
|
|
secret = "b3002c3e321d4b7880360d397db2ccfd"
|
|
options.set("github-app.webhook-secret", secret)
|
|
|
|
future_expires = datetime.now().replace(microsecond=0) + timedelta(minutes=5)
|
|
with assume_test_silo_mode(SiloMode.CONTROL):
|
|
integration = self.create_integration(
|
|
organization=self.organization,
|
|
external_id="12345",
|
|
provider="github",
|
|
metadata={"access_token": "1234", "expires_at": future_expires.isoformat()},
|
|
)
|
|
integration.add_organization(project.organization.id, self.user)
|
|
|
|
repo = Repository.objects.create(
|
|
organization_id=project.organization.id,
|
|
external_id="35129377",
|
|
provider="integrations:github",
|
|
name="baxterthehacker/public-repo",
|
|
)
|
|
|
|
pr = PullRequest.objects.create(
|
|
key="1", repository_id=repo.id, organization_id=project.organization.id
|
|
)
|
|
|
|
response = self.client.post(
|
|
path=url,
|
|
data=PULL_REQUEST_EDITED_EVENT_EXAMPLE,
|
|
content_type="application/json",
|
|
HTTP_X_GITHUB_EVENT="pull_request",
|
|
HTTP_X_HUB_SIGNATURE="sha1=83100642f0cf5d7f6145cf8d04da5d00a09f890f",
|
|
HTTP_X_GITHUB_DELIVERY=str(uuid4()),
|
|
)
|
|
|
|
assert response.status_code == 204
|
|
|
|
pr = PullRequest.objects.get(id=pr.id)
|
|
|
|
assert pr.key == "1"
|
|
assert pr.message == "new edited body. Fixes BAR-7"
|
|
assert pr.title == "new edited title"
|
|
assert pr.author.name == "baxterthehacker"
|
|
|
|
self.assert_group_link(group, pr)
|
|
|
|
@with_feature("organizations:integrations-open-pr-comment")
|
|
@patch("sentry.integrations.github.webhook.metrics")
|
|
def test_closed(self, mock_metrics):
|
|
project = self.project # force creation
|
|
|
|
future_expires = datetime.now().replace(microsecond=0) + timedelta(minutes=5)
|
|
with assume_test_silo_mode(SiloMode.CONTROL):
|
|
integration = self.create_integration(
|
|
organization=self.organization,
|
|
external_id="12345",
|
|
provider="github",
|
|
metadata={"access_token": "1234", "expires_at": future_expires.isoformat()},
|
|
)
|
|
integration.add_organization(project.organization.id, self.user)
|
|
|
|
repo = Repository.objects.create(
|
|
organization_id=project.organization.id,
|
|
external_id="35129377",
|
|
provider="integrations:github",
|
|
name="baxterthehacker/public-repo",
|
|
)
|
|
|
|
response = self.client.post(
|
|
path=self.url,
|
|
data=PULL_REQUEST_CLOSED_EVENT_EXAMPLE,
|
|
content_type="application/json",
|
|
HTTP_X_GITHUB_EVENT="pull_request",
|
|
HTTP_X_HUB_SIGNATURE="sha1=49db856f5658b365b73a2fa73a7cffa543f4d3af",
|
|
HTTP_X_GITHUB_DELIVERY=str(uuid4()),
|
|
)
|
|
|
|
assert response.status_code == 204
|
|
|
|
prs = PullRequest.objects.filter(
|
|
repository_id=repo.id, organization_id=project.organization.id
|
|
)
|
|
|
|
assert len(prs) == 1
|
|
|
|
pr = prs[0]
|
|
|
|
assert pr.key == "1"
|
|
assert pr.message == "new closed body"
|
|
assert pr.title == "new closed title"
|
|
assert pr.author.name == "baxterthehacker"
|
|
assert pr.merge_commit_sha == "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c"
|
|
|
|
assert mock_metrics.incr.call_count == 0
|
|
|
|
def assert_group_link(self, group, pr):
|
|
link = GroupLink.objects.all().first()
|
|
assert link
|
|
assert link.group_id == group.id
|
|
assert link.linked_id == pr.id
|
|
assert link.linked_type == GroupLink.LinkedType.pull_request
|