gitlab.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. from time import time
  2. from sentry.integrations.gitlab.integration import GitlabIntegration
  3. from sentry.models.identity import Identity, IdentityProvider
  4. from sentry.models.integrations.integration import Integration
  5. from sentry.models.repository import Repository
  6. from sentry.silo.base import SiloMode
  7. from sentry.testutils.cases import APITestCase
  8. from sentry.testutils.helpers.integrations import get_installation_of_type
  9. from sentry.testutils.silo import assume_test_silo_mode
  10. EXTERNAL_ID = "example.gitlab.com:group-x"
  11. WEBHOOK_SECRET = "secret-token-value"
  12. WEBHOOK_TOKEN = f"{EXTERNAL_ID}:{WEBHOOK_SECRET}"
  13. class GitLabTestCase(APITestCase):
  14. provider = "gitlab"
  15. def setUp(self):
  16. self.login_as(self.user)
  17. with assume_test_silo_mode(SiloMode.CONTROL):
  18. self.integration = Integration.objects.create(
  19. provider=self.provider,
  20. name="Example Gitlab",
  21. external_id=EXTERNAL_ID,
  22. metadata={
  23. "instance": "example.gitlab.com",
  24. "base_url": "https://example.gitlab.com",
  25. "domain_name": "example.gitlab.com/group-x",
  26. "verify_ssl": False,
  27. "webhook_secret": WEBHOOK_SECRET,
  28. "group_id": 1,
  29. },
  30. )
  31. identity = Identity.objects.create(
  32. idp=IdentityProvider.objects.create(type=self.provider, config={}),
  33. user=self.user,
  34. external_id="gitlab123",
  35. data={
  36. "access_token": "123456789",
  37. "created_at": time(),
  38. "refresh_token": "0987654321",
  39. },
  40. )
  41. self.integration.add_organization(self.organization, self.user, identity.id)
  42. self.installation = get_installation_of_type(
  43. GitlabIntegration, self.integration, self.organization.id
  44. )
  45. @assume_test_silo_mode(SiloMode.REGION)
  46. def create_repo(self, name, external_id=15, url=None, organization_id=None):
  47. instance = self.integration.metadata["instance"]
  48. organization_id = organization_id or self.organization.id
  49. return Repository.objects.create(
  50. organization_id=organization_id,
  51. name=name,
  52. external_id=f"{instance}:{external_id}",
  53. url=url,
  54. config={"project_id": external_id, "path": "example-repo"},
  55. provider="integrations:gitlab",
  56. integration_id=self.integration.id,
  57. )
  58. MERGE_REQUEST_OPENED_EVENT = b"""{
  59. "object_kind": "merge_request",
  60. "user": {
  61. "name": "Administrator",
  62. "username": "root",
  63. "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon"
  64. },
  65. "project": {
  66. "id": 15,
  67. "name": "Sentry",
  68. "description": "",
  69. "web_url": "http://example.com/cool-group/sentry",
  70. "avatar_url": null,
  71. "git_ssh_url": "git@example.com:cool-group/sentry.git",
  72. "git_http_url": "http://example.com/cool-group/sentry.git",
  73. "namespace": "cool-group",
  74. "visibility_level": 0,
  75. "path_with_namespace": "cool-group/sentry",
  76. "default_branch": "master",
  77. "ci_config_path": "",
  78. "homepage": "http://example.com/cool-group/sentry",
  79. "url": "git@example.com:cool-group/sentry.git",
  80. "ssh_url": "git@example.com:cool-group/sentry.git",
  81. "http_url": "http://example.com/cool-group/sentry.git"
  82. },
  83. "object_attributes": {
  84. "id": 90,
  85. "target_branch": "master",
  86. "source_branch": "ms-viewport",
  87. "source_project_id": 14,
  88. "author_id": 51,
  89. "assignee_id": 6,
  90. "title": "Create a new Viewport",
  91. "created_at": "2017-09-20T08:31:45.944Z",
  92. "updated_at": "2017-09-28T12:23:42.365Z",
  93. "milestone_id": null,
  94. "state": "opened",
  95. "merge_status": "unchecked",
  96. "target_project_id": 14,
  97. "iid": 1,
  98. "description": "Create a viewport for things Fixes BAR-9",
  99. "updated_by_id": 1,
  100. "merge_error": null,
  101. "merge_params": {
  102. "force_remove_source_branch": "0"
  103. },
  104. "merge_when_pipeline_succeeds": false,
  105. "merge_user_id": null,
  106. "merge_commit_sha": null,
  107. "deleted_at": null,
  108. "in_progress_merge_commit_sha": null,
  109. "lock_version": 5,
  110. "time_estimate": 0,
  111. "last_edited_at": "2017-09-27T12:43:37.558Z",
  112. "last_edited_by_id": 1,
  113. "head_pipeline_id": 61,
  114. "ref_fetched": true,
  115. "merge_jid": null,
  116. "source": {
  117. "name": "Awesome Project",
  118. "description": "",
  119. "web_url": "http://example.com/awesome_space/awesome_project",
  120. "avatar_url": null,
  121. "git_ssh_url": "git@example.com:awesome_space/awesome_project.git",
  122. "git_http_url": "http://example.com/awesome_space/awesome_project.git",
  123. "namespace": "root",
  124. "visibility_level": 0,
  125. "path_with_namespace": "awesome_space/awesome_project",
  126. "default_branch": "master",
  127. "ci_config_path": "",
  128. "homepage": "http://example.com/awesome_space/awesome_project",
  129. "url": "http://example.com/awesome_space/awesome_project.git",
  130. "ssh_url": "git@example.com:awesome_space/awesome_project.git",
  131. "http_url": "http://example.com/awesome_space/awesome_project.git"
  132. },
  133. "target": {
  134. "name": "Awesome Project",
  135. "description": "Aut reprehenderit ut est.",
  136. "web_url": "http://example.com/awesome_space/awesome_project",
  137. "avatar_url": null,
  138. "git_ssh_url": "git@example.com:awesome_space/awesome_project.git",
  139. "git_http_url": "http://example.com/awesome_space/awesome_project.git",
  140. "namespace": "Awesome Space",
  141. "visibility_level": 0,
  142. "path_with_namespace": "awesome_space/awesome_project",
  143. "default_branch": "master",
  144. "ci_config_path": "",
  145. "homepage": "http://example.com/awesome_space/awesome_project",
  146. "url": "http://example.com/awesome_space/awesome_project.git",
  147. "ssh_url": "git@example.com:awesome_space/awesome_project.git",
  148. "http_url": "http://example.com/awesome_space/awesome_project.git"
  149. },
  150. "last_commit": {
  151. "id": "ba3e0d8ff79c80d5b0bbb4f3e2e343e0aaa662b7",
  152. "message": "fixed readme",
  153. "timestamp": "2017-09-26T16:12:57Z",
  154. "url": "http://example.com/awesome_space/awesome_project/commits/da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
  155. "author": {
  156. "name": "GitLab dev user",
  157. "email": "gitlabdev@dv6700.(none)"
  158. }
  159. },
  160. "work_in_progress": false,
  161. "total_time_spent": 0,
  162. "human_total_time_spent": null,
  163. "human_time_estimate": null
  164. },
  165. "labels": null,
  166. "repository": {
  167. "name": "git-gpg-test",
  168. "url": "git@example.com:awesome_space/awesome_project.git",
  169. "description": "",
  170. "homepage": "http://example.com/awesome_space/awesome_project"
  171. }
  172. }"""
  173. PUSH_EVENT = b"""
  174. {
  175. "object_kind": "push",
  176. "before": "95790bf891e76fee5e1747ab589903a6a1f80f22",
  177. "after": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
  178. "ref": "refs/heads/master",
  179. "checkout_sha": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
  180. "user_id": 4,
  181. "user_name": "John Smith",
  182. "user_username": "jsmith",
  183. "user_email": "john@example.com",
  184. "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80",
  185. "project_id": 15,
  186. "project":{
  187. "id": 15,
  188. "name":"Sentry",
  189. "description":"",
  190. "web_url":"http://example.com/cool-group/sentry",
  191. "avatar_url":null,
  192. "git_ssh_url":"git@example.com:cool-group/sentry.git",
  193. "git_http_url":"http://example.com/cool-group/sentry.git",
  194. "namespace":"Cool Group",
  195. "visibility_level":0,
  196. "path_with_namespace":"cool-group/sentry",
  197. "default_branch":"master",
  198. "homepage":"http://example.com/cool-group/sentry",
  199. "url":"git@example.com:cool-group/sentry.git",
  200. "ssh_url":"git@example.com:cool-group/sentry.git",
  201. "http_url":"http://example.com/cool-group/sentry.git"
  202. },
  203. "repository":{
  204. "name": "Sentry",
  205. "url": "git@example.com:cool-group/sentry.git",
  206. "description": "",
  207. "homepage": "http://example.com/cool-group/sentry",
  208. "git_http_url":"http://example.com/cool-group/sentry.git",
  209. "git_ssh_url":"git@example.com:cool-group/sentry.git",
  210. "visibility_level":0
  211. },
  212. "commits": [
  213. {
  214. "id": "b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
  215. "message": "Update Catalan translation to e38cb41.",
  216. "timestamp": "2011-12-12T14:27:31+02:00",
  217. "url": "http://example.com/cool-group/sentry/commit/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
  218. "author": {
  219. "name": "Jordi",
  220. "email": "jordi@example.org"
  221. },
  222. "added": ["CHANGELOG"],
  223. "modified": ["app/controller/application.rb"],
  224. "removed": []
  225. },
  226. {
  227. "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
  228. "message": "fixed readme",
  229. "timestamp": "2012-01-03T23:36:29+02:00",
  230. "url": "http://example.com/cool-group/sentry/commit/da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
  231. "author": {
  232. "name": "GitLab dev user",
  233. "email": "gitlabdev@example.org"
  234. },
  235. "added": ["CHANGELOG"],
  236. "modified": ["app/controller/application.rb"],
  237. "removed": []
  238. }
  239. ],
  240. "total_commits_count": 2
  241. }
  242. """
  243. PUSH_EVENT_IGNORED_COMMIT = b"""
  244. {
  245. "object_kind": "push",
  246. "before": "95790bf891e76fee5e1747ab589903a6a1f80f22",
  247. "after": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
  248. "ref": "refs/heads/master",
  249. "checkout_sha": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
  250. "user_id": 4,
  251. "user_name": "John Smith",
  252. "user_username": "jsmith",
  253. "user_email": "john@example.com",
  254. "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80",
  255. "project_id": 15,
  256. "project":{
  257. "id": 15,
  258. "name":"Sentry",
  259. "description":"",
  260. "web_url":"http://example.com/cool-group/sentry",
  261. "avatar_url":null,
  262. "git_ssh_url":"git@example.com:cool-group/sentry.git",
  263. "git_http_url":"http://example.com/cool-group/sentry.git",
  264. "namespace":"cool-group",
  265. "visibility_level":0,
  266. "path_with_namespace":"cool-group/sentry",
  267. "default_branch":"master",
  268. "homepage":"http://example.com/cool-group/sentry",
  269. "url":"git@example.com:cool-group/sentry.git",
  270. "ssh_url":"git@example.com:cool-group/sentry.git",
  271. "http_url":"http://example.com/cool-group/sentry.git"
  272. },
  273. "repository":{
  274. "name": "Sentry",
  275. "url": "git@example.com:cool-group/sentry.git",
  276. "description": "",
  277. "homepage": "http://example.com/cool-group/sentry",
  278. "git_http_url":"http://example.com/cool-group/sentry.git",
  279. "git_ssh_url":"git@example.com:cool-group/sentry.git",
  280. "visibility_level":0
  281. },
  282. "commits": [
  283. {
  284. "id": "b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
  285. "message": "Update things #skipsentry",
  286. "timestamp": "2011-12-12T14:27:31+02:00",
  287. "url": "http://example.com/cool-group/sentry/commit/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
  288. "author": {
  289. "name": "Jordi",
  290. "email": "jordi@example.org"
  291. },
  292. "added": ["CHANGELOG"],
  293. "modified": ["app/controller/application.rb"],
  294. "removed": []
  295. }
  296. ],
  297. "total_commits_count": 1
  298. }
  299. """
  300. COMPARE_RESPONSE = r"""
  301. {
  302. "commit": {
  303. "id": "12d65c8dd2b2676fa3ac47d955accc085a37a9c1",
  304. "short_id": "12d65c8dd2b",
  305. "title": "JS fix",
  306. "author_name": "Dmitriy",
  307. "author_email": "dmitriy@example.com",
  308. "created_at": "2014-02-27T10:27:00+02:00"
  309. },
  310. "commits": [{
  311. "id": "12d65c8dd2b2676fa3ac47d955accc085a37a9c1",
  312. "short_id": "12d65c8dd2b",
  313. "title": "JS fix",
  314. "author_name": "Dmitriy",
  315. "author_email": "dmitriy@example.com",
  316. "created_at": "2014-02-27T10:27:00+02:00"
  317. },
  318. {
  319. "id": "8b090c1b79a14f2bd9e8a738f717824ff53aebad",
  320. "short_id": "8b090c1b",
  321. "title": "Fix dmitriy mistake",
  322. "author_name": "Sally",
  323. "author_email": "sally@example.com",
  324. "created_at": "2014-02-27T10:27:00+02:00"
  325. }],
  326. "diffs": [{
  327. "old_path": "files/js/application.js",
  328. "new_path": "files/js/application.js",
  329. "a_mode": null,
  330. "b_mode": "100644",
  331. "diff": "--- a/files/js/application.js\n+++ b/files/js/application.js\n@@ -24,8 +24,10 @@\n //= require g.raphael-min\n //= require g.bar-min\n //= require branch-graph\n-//= require highlightjs.min\n-//= require ace/ace\n //= require_tree .\n //= require d3\n //= require underscore\n+\n+function fix() { \n+ alert(\"Fixed\")\n+}",
  332. "new_file": false,
  333. "renamed_file": false,
  334. "deleted_file": false
  335. }],
  336. "compare_timeout": false,
  337. "compare_same_ref": false
  338. }
  339. """
  340. COMMIT_LIST_RESPONSE = r"""
  341. [
  342. {
  343. "id": "ed899a2f4b50b4370feeea94676502b42383c746",
  344. "short_id": "ed899a2f4b5",
  345. "title": "Replace sanitize with escape once",
  346. "author_name": "Dmitriy",
  347. "author_email": "dmitriy@example.com",
  348. "authored_date": "2018-09-20T11:50:22+03:00",
  349. "committer_name": "Administrator",
  350. "committer_email": "admin@example.com",
  351. "committed_date": "2018-09-20T11:50:22+03:00",
  352. "created_at": "2018-09-20T11:50:22+03:00",
  353. "message": "Replace sanitize with escape once",
  354. "parent_ids": [
  355. "6104942438c14ec7bd21c6cd5bd995272b3faff6"
  356. ]
  357. },
  358. {
  359. "id": "6104942438c14ec7bd21c6cd5bd995272b3faff6",
  360. "short_id": "6104942438c",
  361. "title": "Sanitize for network graph",
  362. "author_name": "randx",
  363. "author_email": "dmitriy@example.com",
  364. "committer_name": "Dmitriy",
  365. "committer_email": "dmitriy@example.com",
  366. "created_at": "2018-09-20T09:06:12+03:00",
  367. "message": "Sanitize for network graph",
  368. "parent_ids": [
  369. "ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba"
  370. ]
  371. }
  372. ]
  373. """
  374. COMMIT_DIFF_RESPONSE = r"""
  375. [
  376. {
  377. "old_path": "files/js/application.js",
  378. "new_path": "files/js/application.js",
  379. "a_mode": null,
  380. "b_mode": "100644",
  381. "diff": "--- a/files/js/application.js\n+++ b/files/js/application.js\n@@ -24,8 +24,10 @@\n //= require g.raphael-min\n //= require g.bar-min\n //= require branch-graph\n-//= require highlightjs.min\n-//= require ace/ace\n //= require_tree .\n //= require d3\n //= require underscore\n+\n+function fix() { \n+ alert(\"Fixed\")\n+}",
  382. "new_file": false,
  383. "renamed_file": false,
  384. "deleted_file": false
  385. },
  386. {
  387. "a_mode": "100644",
  388. "b_mode": "100644",
  389. "deleted_file": false,
  390. "diff": "@@ -1 +1,3 @@\n OH HAI\n+OH HAI\n+OH HAI\n",
  391. "new_file": false,
  392. "new_path": "README.txt",
  393. "old_path": "README.txt",
  394. "renamed_file": false
  395. }
  396. ]
  397. """
  398. # Example taken from https://docs.gitlab.com/ee/api/commits.html#get-a-single-commit
  399. GET_COMMIT_RESPONSE = """
  400. {
  401. "id": "6104942438c14ec7bd21c6cd5bd995272b3faff6",
  402. "short_id": "6104942438c",
  403. "title": "Sanitize for network graph",
  404. "author_name": "randx",
  405. "author_email": "user@example.com",
  406. "committer_name": "Dmitriy",
  407. "committer_email": "user@example.com",
  408. "created_at": "2021-09-20T09:06:12.300+03:00",
  409. "message": "Sanitize for network graph",
  410. "committed_date": "2021-09-20T09:06:12.300+03:00",
  411. "authored_date": "2021-09-20T09:06:12.420+03:00",
  412. "parent_ids": [
  413. "ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba"
  414. ],
  415. "last_pipeline" : {
  416. "id": 8,
  417. "ref": "master",
  418. "sha": "2dc6aa325a317eda67812f05600bdf0fcdc70ab0",
  419. "status": "created"
  420. },
  421. "stats": {
  422. "additions": 15,
  423. "deletions": 10,
  424. "total": 25
  425. },
  426. "status": "running",
  427. "web_url": "https://gitlab.example.com/thedude/gitlab-foss/-/commit/6104942438c14ec7bd21c6cd5bd995272b3faff6"
  428. }"""