gitlab.py 15 KB

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