test_provider.py 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. from functools import cached_property
  2. from unittest.mock import patch
  3. import responses
  4. from sentry.models.integrations.organization_integration import OrganizationIntegration
  5. from sentry.models.repository import Repository
  6. from sentry.silo.base import SiloMode
  7. from sentry.testutils.cases import TestCase
  8. from sentry.testutils.silo import assume_test_silo_mode, region_silo_test
  9. from sentry.utils import json
  10. from sentry_plugins.github.client import GithubPluginAppsClient, GithubPluginClient
  11. from sentry_plugins.github.plugin import GitHubAppsRepositoryProvider, GitHubRepositoryProvider
  12. from sentry_plugins.github.testutils import (
  13. COMPARE_COMMITS_EXAMPLE,
  14. GET_LAST_COMMITS_EXAMPLE,
  15. INTSTALLATION_REPOSITORIES_API_RESPONSE,
  16. LIST_INSTALLATION_API_RESPONSE,
  17. )
  18. @region_silo_test(stable=True)
  19. class GitHubPluginTest(TestCase):
  20. @cached_property
  21. def provider(self):
  22. return GitHubRepositoryProvider("github")
  23. def test_compare_commits(self):
  24. repo = Repository.objects.create(provider="github", name="example", organization_id=1)
  25. res = self.provider._format_commits(repo, json.loads(COMPARE_COMMITS_EXAMPLE)["commits"])
  26. assert res == [
  27. {
  28. "author_email": "support@github.com",
  29. "author_name": "Monalisa Octocat",
  30. "message": "Fix all the bugs",
  31. "id": "6dcb09b5b57875f334f61aebed695e2e4193db5e",
  32. "repository": "example",
  33. }
  34. ]
  35. def test_get_last_commits(self):
  36. repo = Repository.objects.create(provider="github", name="example", organization_id=1)
  37. res = self.provider._format_commits(repo, json.loads(GET_LAST_COMMITS_EXAMPLE)[:10])
  38. assert res == [
  39. {
  40. "author_email": "support@github.com",
  41. "author_name": "Monalisa Octocat",
  42. "message": "Fix all the bugs",
  43. "id": "6dcb09b5b57875f334f61aebed695e2e4193db5e",
  44. "repository": "example",
  45. }
  46. ]
  47. @responses.activate
  48. def test_create_repository(self):
  49. responses.add(
  50. responses.POST,
  51. "https://api.github.com/repos/getsentry/example-repo/hooks",
  52. json={"id": "123456", "events": ["push", "pull_request"]},
  53. )
  54. user = self.create_user()
  55. organization = self.create_organization()
  56. self.create_usersocialauth(
  57. user=user, provider="github", extra_data={"access_token": "abcdefg"}
  58. )
  59. data = {"name": "getsentry/example-repo", "external_id": "654321"}
  60. data = self.provider.create_repository(organization, data, user)
  61. assert data == {
  62. "config": {
  63. "name": "getsentry/example-repo",
  64. "webhook_id": "123456",
  65. "webhook_events": ["push", "pull_request"],
  66. },
  67. "external_id": "654321",
  68. "name": "getsentry/example-repo",
  69. "url": "https://github.com/getsentry/example-repo",
  70. }
  71. request = responses.calls[-1].request
  72. req_json = json.loads(request.body)
  73. assert req_json == {
  74. "active": True,
  75. "config": {
  76. "url": f"http://testserver/plugins/github/organizations/{organization.id}/webhook/",
  77. "secret": self.provider.get_webhook_secret(organization),
  78. "content_type": "json",
  79. },
  80. "name": "web",
  81. "events": ["push", "pull_request"],
  82. }
  83. @responses.activate
  84. def test_delete_repository(self):
  85. responses.add(
  86. responses.DELETE,
  87. "https://api.github.com/repos/getsentry/example-repo/hooks/123456",
  88. json={},
  89. )
  90. user = self.create_user()
  91. organization = self.create_organization()
  92. self.create_usersocialauth(
  93. user=user, provider="github", extra_data={"access_token": "abcdefg"}
  94. )
  95. repo = Repository.objects.create(
  96. provider="github",
  97. name="example-repo",
  98. organization_id=organization.id,
  99. config={
  100. "name": "getsentry/example-repo",
  101. "external_id": "654321",
  102. "webhook_id": "123456",
  103. },
  104. )
  105. self.provider.delete_repository(repo, user)
  106. @responses.activate
  107. def test_update_repository_without_webhook(self):
  108. responses.add(
  109. responses.POST,
  110. "https://api.github.com/repos/getsentry/example-repo/hooks",
  111. json={"id": "123456", "events": ["push", "pull_request"]},
  112. )
  113. user = self.create_user()
  114. organization = self.create_organization()
  115. self.create_usersocialauth(
  116. user=user, provider="github", extra_data={"access_token": "abcdefg"}
  117. )
  118. repo = Repository.objects.create(
  119. provider="github",
  120. name="example-repo",
  121. organization_id=organization.id,
  122. config={"name": "getsentry/example-repo", "external_id": "654321"},
  123. )
  124. self.provider.update_repository(repo, user)
  125. assert repo.config["webhook_id"] == "123456"
  126. assert repo.config["webhook_events"] == ["push", "pull_request"]
  127. @responses.activate
  128. def test_update_repository_with_webhook(self):
  129. responses.add(
  130. responses.PATCH,
  131. "https://api.github.com/repos/getsentry/example-repo/hooks/123456",
  132. json={"id": "123456", "events": ["push", "pull_request"]},
  133. )
  134. user = self.create_user()
  135. organization = self.create_organization()
  136. self.create_usersocialauth(
  137. user=user, provider="github", extra_data={"access_token": "abcdefg"}
  138. )
  139. repo = Repository.objects.create(
  140. provider="github",
  141. name="example-repo",
  142. organization_id=organization.id,
  143. config={
  144. "name": "getsentry/example-repo",
  145. "external_id": "654321",
  146. "webhook_id": "123456",
  147. },
  148. )
  149. self.provider.update_repository(repo, user)
  150. assert repo.config["webhook_id"] == "123456"
  151. assert repo.config["webhook_events"] == ["push", "pull_request"]
  152. @region_silo_test(stable=True)
  153. class GitHubAppsProviderTest(TestCase):
  154. @cached_property
  155. def provider(self):
  156. return GitHubAppsRepositoryProvider("github_apps")
  157. @patch.object(
  158. GithubPluginAppsClient,
  159. "get_repositories",
  160. return_value=json.loads(INTSTALLATION_REPOSITORIES_API_RESPONSE),
  161. )
  162. @patch.object(
  163. GithubPluginClient,
  164. "get_installations",
  165. return_value=json.loads(LIST_INSTALLATION_API_RESPONSE),
  166. )
  167. def test_link_auth(self, *args):
  168. user = self.create_user()
  169. organization = self.create_organization()
  170. self.create_usersocialauth(
  171. user=user, provider="github_apps", extra_data={"access_token": "abcdefg"}
  172. )
  173. integration = self.create_integration(
  174. organization=organization, provider="github_apps", external_id="1"
  175. )
  176. self.provider.link_auth(user, organization, {"integration_id": integration.id})
  177. with assume_test_silo_mode(SiloMode.CONTROL):
  178. assert OrganizationIntegration.objects.filter(
  179. organization_id=organization.id, integration=integration
  180. ).exists()
  181. def test_delete_repository(self):
  182. user = self.create_user()
  183. organization = self.create_organization()
  184. integration = self.create_integration(
  185. organization=organization, provider="github_apps", external_id="1"
  186. )
  187. repo = Repository.objects.create(
  188. name="example-repo",
  189. provider="github_apps",
  190. organization_id=organization.id,
  191. integration_id=integration.id,
  192. )
  193. # just check that it doesn't throw / try to delete a webhook
  194. assert self.provider.delete_repository(repo=repo, actor=user) is None
  195. @patch.object(GithubPluginAppsClient, "get_last_commits", return_value=[])
  196. def test_compare_commits_no_start(self, mock_get_last_commits):
  197. organization = self.create_organization()
  198. integration = self.create_integration(
  199. organization=organization, provider="github_apps", external_id="1"
  200. )
  201. repo = Repository.objects.create(
  202. name="example-repo",
  203. provider="github_apps",
  204. organization_id=organization.id,
  205. integration_id=integration.id,
  206. config={"name": "example-repo"},
  207. )
  208. self.provider.compare_commits(repo, None, "a" * 40)
  209. assert mock_get_last_commits.called
  210. @patch.object(GithubPluginAppsClient, "compare_commits", return_value={"commits": []})
  211. def test_compare_commits(self, mock_compare_commits):
  212. organization = self.create_organization()
  213. integration = self.create_integration(
  214. organization=organization, provider="github_apps", external_id="1"
  215. )
  216. repo = Repository.objects.create(
  217. name="example-repo",
  218. provider="github_apps",
  219. organization_id=organization.id,
  220. integration_id=integration.id,
  221. config={"name": "example-repo"},
  222. )
  223. self.provider.compare_commits(repo, "b" * 40, "a" * 40)
  224. assert mock_compare_commits.called