test_organization_releases.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806
  1. from __future__ import absolute_import
  2. from mock import patch
  3. from base64 import b64encode
  4. from datetime import datetime
  5. from django.core.urlresolvers import reverse
  6. from sentry.models import (
  7. Activity, ApiKey, ApiToken, Release,
  8. ReleaseCommit, ReleaseProject, Repository
  9. )
  10. from sentry.testutils import APITestCase
  11. class OrganizationReleaseListTest(APITestCase):
  12. def test_simple(self):
  13. user = self.create_user(is_staff=False, is_superuser=False)
  14. org = self.organization
  15. org2 = self.create_organization()
  16. org.flags.allow_joinleave = False
  17. org.save()
  18. team1 = self.create_team(organization=org)
  19. team2 = self.create_team(organization=org)
  20. project1 = self.create_project(team=team1, organization=org)
  21. project2 = self.create_project(team=team2, organization=org2)
  22. project3 = self.create_project(team=team1, organization=org)
  23. self.create_member(teams=[team1], user=user, organization=org)
  24. self.login_as(user=user)
  25. release1 = Release.objects.create(
  26. organization_id=org.id,
  27. version='1',
  28. date_added=datetime(2013, 8, 13, 3, 8, 24, 880386),
  29. )
  30. release1.add_project(project1)
  31. release2 = Release.objects.create(
  32. organization_id=org2.id,
  33. version='2',
  34. date_added=datetime(2013, 8, 14, 3, 8, 24, 880386),
  35. )
  36. release2.add_project(project2)
  37. release3 = Release.objects.create(
  38. organization_id=org.id,
  39. version='3',
  40. date_added=datetime(2013, 8, 12, 3, 8, 24, 880386),
  41. date_released=datetime(2013, 8, 15, 3, 8, 24, 880386),
  42. )
  43. release3.add_project(project3)
  44. release4 = Release.objects.create(
  45. organization_id=org.id,
  46. version='4',
  47. date_added=datetime(2013, 8, 14, 3, 8, 24, 880386),
  48. )
  49. release4.add_project(project3)
  50. url = reverse('sentry-api-0-organization-releases', kwargs={
  51. 'organization_slug': org.slug
  52. })
  53. response = self.client.get(url, format='json')
  54. assert response.status_code == 200, response.content
  55. assert len(response.data) == 3
  56. assert response.data[0]['version'] == release3.version
  57. assert response.data[1]['version'] == release4.version
  58. assert response.data[2]['version'] == release1.version
  59. def test_query_filter(self):
  60. user = self.create_user(is_staff=False, is_superuser=False)
  61. org = self.organization
  62. org.flags.allow_joinleave = False
  63. org.save()
  64. team = self.create_team(organization=org)
  65. project = self.create_project(team=team, organization=org)
  66. self.create_member(teams=[team], user=user, organization=org)
  67. self.login_as(user=user)
  68. release = Release.objects.create(
  69. organization_id=org.id,
  70. version='foobar',
  71. date_added=datetime(2013, 8, 13, 3, 8, 24, 880386),
  72. )
  73. release.add_project(project)
  74. release2 = Release.objects.create(
  75. organization_id=org.id,
  76. version='sdfsdfsdf',
  77. date_added=datetime(2013, 8, 13, 3, 8, 24, 880386),
  78. )
  79. release2.add_project(project)
  80. url = reverse('sentry-api-0-organization-releases', kwargs={
  81. 'organization_slug': org.slug
  82. })
  83. response = self.client.get(url + '?query=foo', format='json')
  84. assert response.status_code == 200, response.content
  85. assert len(response.data) == 1
  86. assert response.data[0]['version'] == release.version
  87. response = self.client.get(url + '?query=bar', format='json')
  88. assert response.status_code == 200, response.content
  89. assert len(response.data) == 0
  90. def test_project_permissions(self):
  91. user = self.create_user(is_staff=False, is_superuser=False)
  92. org = self.create_organization()
  93. org.flags.allow_joinleave = False
  94. org.save()
  95. team1 = self.create_team(organization=org)
  96. team2 = self.create_team(organization=org)
  97. project1 = self.create_project(team=team1, organization=org)
  98. project2 = self.create_project(team=team2, organization=org)
  99. self.create_member(teams=[team1], user=user, organization=org)
  100. self.login_as(user=user)
  101. release1 = Release.objects.create(
  102. organization_id=org.id,
  103. version='1',
  104. date_added=datetime(2013, 8, 13, 3, 8, 24, 880386),
  105. )
  106. release1.add_project(project1)
  107. release2 = Release.objects.create(
  108. organization_id=org.id,
  109. version='2',
  110. date_added=datetime(2013, 8, 14, 3, 8, 24, 880386),
  111. )
  112. release2.add_project(project2)
  113. release3 = Release.objects.create(
  114. organization_id=org.id,
  115. version='3',
  116. date_added=datetime(2013, 8, 12, 3, 8, 24, 880386),
  117. date_released=datetime(2013, 8, 15, 3, 8, 24, 880386),
  118. )
  119. release3.add_project(project1)
  120. url = reverse('sentry-api-0-organization-releases', kwargs={
  121. 'organization_slug': org.slug
  122. })
  123. response = self.client.get(url, format='json')
  124. assert response.status_code == 200, response.content
  125. assert len(response.data) == 2
  126. assert response.data[0]['version'] == release3.version
  127. assert response.data[1]['version'] == release1.version
  128. class OrganizationReleaseCreateTest(APITestCase):
  129. def test_minimal(self):
  130. user = self.create_user(is_staff=False, is_superuser=False)
  131. org = self.create_organization()
  132. org.flags.allow_joinleave = False
  133. org.save()
  134. team = self.create_team(organization=org)
  135. project = self.create_project(
  136. name='foo',
  137. organization=org,
  138. team=team
  139. )
  140. project2 = self.create_project(
  141. name='bar',
  142. organization=org,
  143. team=team
  144. )
  145. self.create_member(teams=[team], user=user, organization=org)
  146. self.login_as(user=user)
  147. url = reverse('sentry-api-0-organization-releases', kwargs={
  148. 'organization_slug': org.slug,
  149. })
  150. response = self.client.post(url, data={
  151. 'version': '1.2.1',
  152. 'projects': [project.slug, project2.slug]
  153. })
  154. assert response.status_code == 201, response.content
  155. assert response.data['version']
  156. release = Release.objects.get(
  157. version=response.data['version'],
  158. )
  159. assert not release.owner
  160. assert release.organization == org
  161. assert ReleaseProject.objects.filter(
  162. release=release, project=project
  163. ).exists()
  164. assert ReleaseProject.objects.filter(
  165. release=release, project=project2
  166. ).exists()
  167. def test_duplicate(self):
  168. user = self.create_user(is_staff=False, is_superuser=False)
  169. org = self.create_organization()
  170. org.flags.allow_joinleave = False
  171. org.save()
  172. team = self.create_team(organization=org)
  173. project = self.create_project(
  174. name='foo',
  175. organization=org,
  176. team=team
  177. )
  178. self.create_member(teams=[team], user=user, organization=org)
  179. self.login_as(user=user)
  180. release = Release.objects.create(version='1.2.1',
  181. organization=org)
  182. url = reverse('sentry-api-0-organization-releases', kwargs={
  183. 'organization_slug': org.slug,
  184. })
  185. response = self.client.post(url, data={
  186. 'version': '1.2.1',
  187. 'projects': [project.slug]
  188. })
  189. # should be 201 because project was added
  190. assert response.status_code == 201, response.content
  191. assert Release.objects.filter(
  192. version='1.2.1', organization=org
  193. ).count() == 1
  194. # make sure project was added
  195. assert ReleaseProject.objects.filter(
  196. release=release, project=project
  197. ).exists()
  198. def test_activity(self):
  199. user = self.create_user(is_staff=False, is_superuser=False)
  200. org = self.create_organization()
  201. org.flags.allow_joinleave = False
  202. org.save()
  203. team = self.create_team(organization=org)
  204. project = self.create_project(
  205. name='foo',
  206. organization=org,
  207. team=team
  208. )
  209. project2 = self.create_project(
  210. name='bar',
  211. organization=org,
  212. team=team
  213. )
  214. self.create_member(teams=[team], user=user, organization=org)
  215. self.login_as(user=user)
  216. release = Release.objects.create(version='1.2.1',
  217. date_released=datetime.utcnow(),
  218. organization=org)
  219. release.add_project(project)
  220. url = reverse('sentry-api-0-organization-releases', kwargs={
  221. 'organization_slug': org.slug,
  222. })
  223. response = self.client.post(url, data={
  224. 'version': '1.2.1',
  225. 'projects': [project.slug]
  226. })
  227. assert response.status_code == 208, response.content
  228. response = self.client.post(url, data={
  229. 'version': '1.2.1',
  230. 'projects': [project.slug, project2.slug]
  231. })
  232. # should be 201 because 1 project was added
  233. assert response.status_code == 201, response.content
  234. assert not Activity.objects.filter(
  235. type=Activity.RELEASE,
  236. project=project,
  237. ident=release.version
  238. ).exists()
  239. assert Activity.objects.filter(
  240. type=Activity.RELEASE,
  241. project=project2,
  242. ident=release.version
  243. ).exists()
  244. def test_version_whitespace(self):
  245. user = self.create_user(is_staff=False, is_superuser=False)
  246. org = self.create_organization()
  247. org.flags.allow_joinleave = False
  248. org.save()
  249. team = self.create_team(organization=org)
  250. project = self.create_project(
  251. name='foo',
  252. organization=org,
  253. team=team
  254. )
  255. self.create_member(teams=[team], user=user, organization=org)
  256. self.login_as(user=user)
  257. url = reverse('sentry-api-0-organization-releases', kwargs={
  258. 'organization_slug': org.slug
  259. })
  260. response = self.client.post(url, data={
  261. 'version': '1.2.3\n',
  262. 'projects': [project.slug]
  263. })
  264. assert response.status_code == 400, response.content
  265. response = self.client.post(url, data={
  266. 'version': '\n1.2.3',
  267. 'projects': [project.slug]
  268. })
  269. assert response.status_code == 400, response.content
  270. response = self.client.post(url, data={
  271. 'version': '1.\n2.3',
  272. 'projects': [project.slug]
  273. })
  274. assert response.status_code == 400, response.content
  275. response = self.client.post(url, data={
  276. 'version': '1.2.3\f',
  277. 'projects': [project.slug]
  278. })
  279. assert response.status_code == 400, response.content
  280. response = self.client.post(url, data={
  281. 'version': '1.2.3\t',
  282. 'projects': [project.slug]
  283. })
  284. assert response.status_code == 400, response.content
  285. response = self.client.post(url, data={
  286. 'version': '1.2.3+dev',
  287. 'projects': [project.slug]
  288. })
  289. assert response.status_code == 201, response.content
  290. assert response.data['version'] == '1.2.3+dev'
  291. release = Release.objects.get(
  292. organization_id=org.id,
  293. version=response.data['version'],
  294. )
  295. assert not release.owner
  296. def test_features(self):
  297. user = self.create_user(is_staff=False, is_superuser=False)
  298. org = self.create_organization()
  299. org.flags.allow_joinleave = False
  300. org.save()
  301. team = self.create_team(organization=org)
  302. project = self.create_project(
  303. name='foo',
  304. organization=org,
  305. team=team
  306. )
  307. self.create_member(teams=[team], user=user, organization=org)
  308. self.login_as(user=user)
  309. url = reverse('sentry-api-0-organization-releases', kwargs={
  310. 'organization_slug': org.slug
  311. })
  312. response = self.client.post(url, data={
  313. 'version': '1.2.1',
  314. 'owner': self.user.email,
  315. 'projects': [project.slug]
  316. })
  317. assert response.status_code == 201, response.content
  318. assert response.data['version']
  319. release = Release.objects.get(
  320. organization_id=org.id,
  321. version=response.data['version'],
  322. )
  323. assert release.owner == self.user
  324. def test_commits(self):
  325. user = self.create_user(is_staff=False, is_superuser=False)
  326. org = self.create_organization()
  327. org.flags.allow_joinleave = False
  328. org.save()
  329. team = self.create_team(organization=org)
  330. project = self.create_project(
  331. name='foo',
  332. organization=org,
  333. team=team
  334. )
  335. self.create_member(teams=[team], user=user, organization=org)
  336. self.login_as(user=user)
  337. url = reverse('sentry-api-0-organization-releases', kwargs={
  338. 'organization_slug': org.slug
  339. })
  340. response = self.client.post(url, data={
  341. 'version': '1.2.1',
  342. 'commits': [
  343. {'id': 'a' * 40},
  344. {'id': 'b' * 40},
  345. ],
  346. 'projects': [project.slug]
  347. })
  348. assert response.status_code == 201, (response.status_code, response.content)
  349. assert response.data['version']
  350. release = Release.objects.get(
  351. organization_id=org.id,
  352. version=response.data['version'],
  353. )
  354. rc_list = list(ReleaseCommit.objects.filter(
  355. release=release,
  356. ).select_related('commit', 'commit__author').order_by('order'))
  357. assert len(rc_list) == 2
  358. for rc in rc_list:
  359. assert rc.organization_id
  360. @patch('sentry.tasks.commits.fetch_commits')
  361. def test_commits_from_provider(self, mock_fetch_commits):
  362. user = self.create_user(is_staff=False, is_superuser=False)
  363. org = self.create_organization()
  364. org.flags.allow_joinleave = False
  365. org.save()
  366. repo = Repository.objects.create(
  367. organization_id=org.id,
  368. name='example/example',
  369. provider='dummy',
  370. )
  371. repo2 = Repository.objects.create(
  372. organization_id=org.id,
  373. name='example/example2',
  374. provider='dummy',
  375. )
  376. team = self.create_team(organization=org)
  377. project = self.create_project(
  378. name='foo',
  379. organization=org,
  380. team=team
  381. )
  382. self.create_member(teams=[team], user=user, organization=org)
  383. self.login_as(user=user)
  384. url = reverse('sentry-api-0-organization-releases', kwargs={
  385. 'organization_slug': org.slug
  386. })
  387. self.client.post(url, data={
  388. 'version': '1',
  389. 'refs': [
  390. {'commit': '0' * 40, 'repository': repo.name},
  391. {'commit': '0' * 40, 'repository': repo2.name},
  392. ],
  393. 'projects': [project.slug]
  394. })
  395. response = self.client.post(url, data={
  396. 'version': '1.2.1',
  397. 'refs': [
  398. {'commit': 'a' * 40, 'repository': repo.name},
  399. {'commit': 'b' * 40, 'repository': repo2.name},
  400. ],
  401. 'projects': [project.slug]
  402. })
  403. assert response.status_code == 201
  404. mock_fetch_commits.apply_async.assert_called_with(
  405. kwargs={
  406. 'release_id': Release.objects.get(version='1.2.1', organization=org).id,
  407. 'user_id': user.id,
  408. 'refs': [
  409. {'commit': 'a' * 40, 'repository': repo.name},
  410. {'commit': 'b' * 40, 'repository': repo2.name},
  411. ],
  412. 'prev_release_id': Release.objects.get(version='1', organization=org).id,
  413. }
  414. )
  415. @patch('sentry.tasks.commits.fetch_commits')
  416. def test_commits_from_provider_deprecated_head_commits(self, mock_fetch_commits):
  417. user = self.create_user(is_staff=False, is_superuser=False)
  418. org = self.create_organization()
  419. org.flags.allow_joinleave = False
  420. org.save()
  421. repo = Repository.objects.create(
  422. organization_id=org.id,
  423. name='example/example',
  424. provider='dummy',
  425. )
  426. repo2 = Repository.objects.create(
  427. organization_id=org.id,
  428. name='example/example2',
  429. provider='dummy',
  430. )
  431. team = self.create_team(organization=org)
  432. project = self.create_project(
  433. name='foo',
  434. organization=org,
  435. team=team
  436. )
  437. self.create_member(teams=[team], user=user, organization=org)
  438. self.login_as(user=user)
  439. url = reverse('sentry-api-0-organization-releases', kwargs={
  440. 'organization_slug': org.slug
  441. })
  442. self.client.post(url, data={
  443. 'version': '1',
  444. 'headCommits': [
  445. {'currentId': '0' * 40, 'repository': repo.name},
  446. {'currentId': '0' * 40, 'repository': repo2.name},
  447. ],
  448. 'projects': [project.slug]
  449. })
  450. response = self.client.post(url, data={
  451. 'version': '1.2.1',
  452. 'headCommits': [
  453. {'currentId': 'a' * 40, 'repository': repo.name},
  454. {'currentId': 'b' * 40, 'repository': repo2.name},
  455. ],
  456. 'projects': [project.slug]
  457. })
  458. mock_fetch_commits.apply_async.assert_called_with(
  459. kwargs={
  460. 'release_id': Release.objects.get(version='1.2.1', organization=org).id,
  461. 'user_id': user.id,
  462. 'refs': [
  463. {'commit': 'a' * 40, 'repository': repo.name, 'previousCommit': None},
  464. {'commit': 'b' * 40, 'repository': repo2.name, 'previousCommit': None},
  465. ],
  466. 'prev_release_id': Release.objects.get(version='1', organization=org).id,
  467. }
  468. )
  469. assert response.status_code == 201
  470. def test_bad_project_slug(self):
  471. user = self.create_user(is_staff=False, is_superuser=False)
  472. org = self.create_organization()
  473. org.flags.allow_joinleave = False
  474. org.save()
  475. team = self.create_team(organization=org)
  476. project = self.create_project(
  477. name='foo',
  478. organization=org,
  479. team=team
  480. )
  481. self.create_member(teams=[team], user=user, organization=org)
  482. self.login_as(user=user)
  483. url = reverse('sentry-api-0-organization-releases', kwargs={
  484. 'organization_slug': org.slug
  485. })
  486. response = self.client.post(url, data={
  487. 'version': '1.2.1',
  488. 'projects': [project.slug, 'banana']
  489. })
  490. assert response.status_code == 400
  491. assert 'Invalid project slugs' in response.content
  492. def test_project_permissions(self):
  493. user = self.create_user(is_staff=False, is_superuser=False)
  494. org = self.create_organization()
  495. org.flags.allow_joinleave = False
  496. org.save()
  497. team1 = self.create_team(organization=org)
  498. team2 = self.create_team(organization=org)
  499. project1 = self.create_project(team=team1, organization=org)
  500. project2 = self.create_project(team=team2, organization=org)
  501. self.create_member(teams=[team1], user=user, organization=org)
  502. self.login_as(user=user)
  503. release1 = Release.objects.create(
  504. organization_id=org.id,
  505. version='1',
  506. date_added=datetime(2013, 8, 13, 3, 8, 24, 880386),
  507. )
  508. release1.add_project(project1)
  509. release2 = Release.objects.create(
  510. organization_id=org.id,
  511. version='2',
  512. date_added=datetime(2013, 8, 14, 3, 8, 24, 880386),
  513. )
  514. release2.add_project(project2)
  515. release3 = Release.objects.create(
  516. organization_id=org.id,
  517. version='3',
  518. date_added=datetime(2013, 8, 12, 3, 8, 24, 880386),
  519. date_released=datetime(2013, 8, 15, 3, 8, 24, 880386),
  520. )
  521. release3.add_project(project1)
  522. url = reverse('sentry-api-0-organization-releases', kwargs={
  523. 'organization_slug': org.slug
  524. })
  525. response = self.client.post(url, data={
  526. 'version': '1.2.1',
  527. 'projects': [project1.slug, project2.slug]
  528. })
  529. assert response.status_code == 400
  530. assert 'Invalid project slugs' in response.content
  531. response = self.client.post(url, data={
  532. 'version': '1.2.1',
  533. 'projects': [project1.slug]
  534. })
  535. assert response.status_code == 201, response.content
  536. def test_api_key(self):
  537. org = self.create_organization()
  538. org.flags.allow_joinleave = False
  539. org.save()
  540. org2 = self.create_organization()
  541. team1 = self.create_team(organization=org)
  542. project1 = self.create_project(team=team1, organization=org)
  543. release1 = Release.objects.create(
  544. organization_id=org.id,
  545. version='1',
  546. date_added=datetime(2013, 8, 13, 3, 8, 24, 880386),
  547. )
  548. release1.add_project(project1)
  549. url = reverse('sentry-api-0-organization-releases', kwargs={
  550. 'organization_slug': org.slug
  551. })
  552. # test right org, wrong permissions level
  553. bad_api_key = ApiKey.objects.create(
  554. organization=org,
  555. scope_list=['project:read'],
  556. )
  557. response = self.client.post(
  558. url,
  559. data={
  560. 'version': '1.2.1',
  561. 'projects': [
  562. project1.slug]},
  563. HTTP_AUTHORIZATION='Basic ' +
  564. b64encode(
  565. '{}:'.format(
  566. bad_api_key.key)))
  567. assert response.status_code == 403
  568. # test wrong org, right permissions level
  569. wrong_org_api_key = ApiKey.objects.create(
  570. organization=org2,
  571. scope_list=['project:write'],
  572. )
  573. response = self.client.post(
  574. url,
  575. data={
  576. 'version': '1.2.1',
  577. 'projects': [
  578. project1.slug]},
  579. HTTP_AUTHORIZATION='Basic ' +
  580. b64encode(
  581. '{}:'.format(
  582. wrong_org_api_key.key)))
  583. assert response.status_code == 403
  584. # test right org, right permissions level
  585. good_api_key = ApiKey.objects.create(
  586. organization=org,
  587. scope_list=['project:write'],
  588. )
  589. response = self.client.post(
  590. url,
  591. data={
  592. 'version': '1.2.1',
  593. 'projects': [
  594. project1.slug]},
  595. HTTP_AUTHORIZATION='Basic ' +
  596. b64encode(
  597. '{}:'.format(
  598. good_api_key.key)))
  599. assert response.status_code == 201, response.content
  600. @patch('sentry.tasks.commits.fetch_commits')
  601. def test_api_token(self, mock_fetch_commits):
  602. user = self.create_user(is_staff=False, is_superuser=False)
  603. org = self.create_organization()
  604. org.flags.allow_joinleave = False
  605. org.save()
  606. repo = Repository.objects.create(
  607. organization_id=org.id,
  608. name='getsentry/sentry',
  609. provider='dummy',
  610. )
  611. repo2 = Repository.objects.create(
  612. organization_id=org.id,
  613. name='getsentry/sentry-plugins',
  614. provider='dummy',
  615. )
  616. api_token = ApiToken.objects.create(
  617. user=user,
  618. scope_list=['project:releases'],
  619. )
  620. team1 = self.create_team(organization=org)
  621. self.create_member(teams=[team1], user=user, organization=org)
  622. project1 = self.create_project(team=team1, organization=org)
  623. release1 = Release.objects.create(
  624. organization_id=org.id,
  625. version='1',
  626. date_added=datetime(2013, 8, 13, 3, 8, 24, 880386),
  627. )
  628. release1.add_project(project1)
  629. url = reverse('sentry-api-0-organization-releases', kwargs={
  630. 'organization_slug': org.slug
  631. })
  632. response = self.client.post(url, data={
  633. 'version': '1.2.1',
  634. 'refs': [
  635. {'commit': 'a' * 40, 'repository': repo.name, 'previousCommit': 'c' * 40},
  636. {'commit': 'b' * 40, 'repository': repo2.name},
  637. ],
  638. 'projects': [project1.slug]
  639. }, HTTP_AUTHORIZATION='Bearer {}'.format(api_token.token))
  640. mock_fetch_commits.apply_async.assert_called_with(
  641. kwargs={
  642. 'release_id': Release.objects.get(version='1.2.1', organization=org).id,
  643. 'user_id': user.id,
  644. 'refs': [
  645. {'commit': 'a' * 40, 'repository': repo.name, 'previousCommit': 'c' * 40},
  646. {'commit': 'b' * 40, 'repository': repo2.name},
  647. ],
  648. 'prev_release_id': release1.id,
  649. }
  650. )
  651. assert response.status_code == 201
  652. def test_bad_repo_name(self):
  653. user = self.create_user(is_staff=False, is_superuser=False)
  654. org = self.create_organization()
  655. org.flags.allow_joinleave = False
  656. org.save()
  657. team = self.create_team(organization=org)
  658. project = self.create_project(
  659. name='foo',
  660. organization=org,
  661. team=team
  662. )
  663. self.create_member(teams=[team], user=user, organization=org)
  664. self.login_as(user=user)
  665. url = reverse('sentry-api-0-organization-releases', kwargs={
  666. 'organization_slug': org.slug
  667. })
  668. response = self.client.post(url, data={
  669. 'version': '1.2.1',
  670. 'projects': [project.slug],
  671. 'refs': [{
  672. 'repository': 'not_a_repo',
  673. 'commit': 'a' * 40,
  674. }]
  675. })
  676. assert response.status_code == 400
  677. assert response.data == {
  678. 'refs': [u'Invalid repository names: not_a_repo']
  679. }