gitlab.py 15 KB

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