123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438 |
- from datetime import datetime, timedelta
- from unittest.mock import patch
- from uuid import uuid4
- from django.utils import timezone
- from fixtures.github import (
- 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.models import Commit, CommitAuthor, GroupLink, Integration, PullRequest, Repository
- from sentry.testutils import APITestCase
- from sentry.testutils.silo import exempt_from_silo_limits, region_silo_test
- @region_silo_test(stable=True)
- class WebhookTest(APITestCase):
- def test_get(self):
- url = "/extensions/github/webhook/"
- response = self.client.get(url)
- assert response.status_code == 405
- def test_unregistered_event(self):
- project = self.project # noqa force creation
- url = "/extensions/github/webhook/"
- secret = "b3002c3e321d4b7880360d397db2ccfd"
- options.set("github-app.webhook-secret", secret)
- response = self.client.post(
- path=url,
- data=PUSH_EVENT_EXAMPLE_INSTALLATION,
- content_type="application/json",
- HTTP_X_GITHUB_EVENT="UnregisteredEvent",
- HTTP_X_HUB_SIGNATURE="sha1=56a3df597e02adbc17fb617502c70e19d96a6136",
- HTTP_X_GITHUB_DELIVERY=str(uuid4()),
- )
- assert response.status_code == 204
- def test_invalid_signature_event(self):
- url = "/extensions/github/webhook/"
- secret = "2d7565c3537847b789d6995dca8d9f84"
- options.set("github-app.webhook-secret", secret)
- response = self.client.post(
- path=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
- @region_silo_test(stable=True)
- class PushEventWebhookTest(APITestCase):
- @patch("sentry.integrations.github.client.get_jwt")
- def test_simple(self, mock_get_jwt):
- mock_get_jwt.return_value = ""
- project = self.project # force creation
- url = "/extensions/github/webhook/"
- secret = "b3002c3e321d4b7880360d397db2ccfd"
- options.set("github-app.webhook-secret", secret)
- 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 exempt_from_silo_limits():
- integration = Integration.objects.create(
- external_id="12345",
- provider="github",
- metadata={"access_token": "1234", "expires_at": future_expires.isoformat()},
- )
- integration.add_organization(project.organization, self.user)
- response = self.client.post(
- path=url,
- data=PUSH_EVENT_EXAMPLE_INSTALLATION,
- content_type="application/json",
- HTTP_X_GITHUB_EVENT="push",
- HTTP_X_HUB_SIGNATURE="sha1=56a3df597e02adbc17fb617502c70e19d96a6136",
- 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 = commit_list[0]
- assert commit.key == "133d60480286590a610a0eb7352ff6e02b9674c4"
- assert commit.message == "Update README.md (àgain)"
- assert commit.author.name == "bàxterthehacker"
- assert commit.author.email == "baxterthehacker@users.noreply.github.com"
- 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 == "baxterthehacker@users.noreply.github.com"
- assert commit.author.external_id is None
- assert commit.date_added == datetime(2015, 5, 5, 23, 40, 15, tzinfo=timezone.utc)
- def test_anonymous_lookup(self):
- project = self.project # force creation
- url = "/extensions/github/webhook/"
- secret = "b3002c3e321d4b7880360d397db2ccfd"
- options.set("github-app.webhook-secret", secret)
- future_expires = datetime.now().replace(microsecond=0) + timedelta(minutes=5)
- with exempt_from_silo_limits():
- integration = Integration.objects.create(
- provider="github",
- external_id="12345",
- name="octocat",
- metadata={"access_token": "1234", "expires_at": future_expires.isoformat()},
- )
- integration.add_organization(project.organization, self.user)
- 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="baxterthehacker@example.com",
- name="bàxterthehacker",
- )
- response = self.client.post(
- path=url,
- data=PUSH_EVENT_EXAMPLE_INSTALLATION,
- content_type="application/json",
- HTTP_X_GITHUB_EVENT="push",
- HTTP_X_HUB_SIGNATURE="sha1=56a3df597e02adbc17fb617502c70e19d96a6136",
- 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")
- )
- # should be skipping the #skipsentry commit
- assert len(commit_list) == 2
- commit = commit_list[0]
- assert commit.key == "133d60480286590a610a0eb7352ff6e02b9674c4"
- assert commit.message == "Update README.md (àgain)"
- assert commit.author.name == "bàxterthehacker"
- assert commit.author.email == "baxterthehacker@example.com"
- 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 == "baxterthehacker@example.com"
- assert commit.date_added == datetime(2015, 5, 5, 23, 40, 15, tzinfo=timezone.utc)
- @patch("sentry.integrations.github.client.get_jwt")
- def test_multiple_orgs(self, mock_get_jwt):
- mock_get_jwt.return_value = ""
- project = self.project # force creation
- url = "/extensions/github/webhook/"
- secret = "b3002c3e321d4b7880360d397db2ccfd"
- options.set("github-app.webhook-secret", secret)
- 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 exempt_from_silo_limits():
- integration = Integration.objects.create(
- external_id="12345",
- provider="github",
- metadata={"access_token": "1234", "expires_at": future_expires.isoformat()},
- )
- integration.add_organization(project.organization, self.user)
- org2 = self.create_organization()
- project2 = self.create_project(organization=org2, name="bar")
- Repository.objects.create(
- organization_id=project2.organization.id,
- external_id="77",
- provider="integrations:github",
- name="another/repo",
- )
- future_expires = datetime.now().replace(microsecond=0) + timedelta(minutes=5)
- with exempt_from_silo_limits():
- integration = Integration.objects.create(
- external_id="99",
- provider="github",
- metadata={"access_token": "1234", "expires_at": future_expires.isoformat()},
- )
- integration.add_organization(org2, self.user)
- response = self.client.post(
- path=url,
- data=PUSH_EVENT_EXAMPLE_INSTALLATION,
- content_type="application/json",
- HTTP_X_GITHUB_EVENT="push",
- HTTP_X_HUB_SIGNATURE="sha1=56a3df597e02adbc17fb617502c70e19d96a6136",
- 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
- @region_silo_test(stable=True)
- class PullRequestEventWebhook(APITestCase):
- def test_opened(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 exempt_from_silo_limits():
- integration = Integration.objects.create(
- provider="github",
- external_id="12345",
- name="octocat",
- metadata={"access_token": "1234", "expires_at": future_expires.isoformat()},
- )
- integration.add_organization(project.organization, 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=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
- 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)
- 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 exempt_from_silo_limits():
- integration = Integration.objects.create(
- provider="github",
- external_id="12345",
- name="octocat",
- metadata={"access_token": "1234", "expires_at": future_expires.isoformat()},
- )
- integration.add_organization(project.organization, 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)
- def test_closed(self):
- project = self.project # force creation
- url = "/extensions/github/webhook/"
- secret = "b3002c3e321d4b7880360d397db2ccfd"
- options.set("github-app.webhook-secret", secret)
- future_expires = datetime.now().replace(microsecond=0) + timedelta(minutes=5)
- with exempt_from_silo_limits():
- integration = Integration.objects.create(
- provider="github",
- external_id="12345",
- name="octocat",
- metadata={"access_token": "1234", "expires_at": future_expires.isoformat()},
- )
- integration.add_organization(project.organization, 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=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"
- 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
|