Skip to content

Commit 5f8e6aa

Browse files
authored
rename head commits to refs, currentId to commit, and previousId to previousCommit (#5199)
1 parent 5d555e7 commit 5f8e6aa

File tree

6 files changed

+203
-24
lines changed

6 files changed

+203
-24
lines changed

src/sentry/api/endpoints/organization_release_details.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
from sentry.api.exceptions import ResourceDoesNotExist
1010
from sentry.api.serializers import serialize
1111
from sentry.api.serializers.rest_framework import (
12-
CommitSerializer, ListField, ReleaseHeadCommitSerializer
12+
CommitSerializer, ListField, ReleaseHeadCommitSerializerDeprecated,
13+
ReleaseHeadCommitSerializer,
1314
)
1415
from sentry.models import Activity, Group, Release, ReleaseFile
1516
from sentry.utils.apidocs import scenario, attach_scenarios
@@ -47,7 +48,8 @@ class ReleaseSerializer(serializers.Serializer):
4748
dateStarted = serializers.DateTimeField(required=False)
4849
dateReleased = serializers.DateTimeField(required=False)
4950
commits = ListField(child=CommitSerializer(), required=False)
50-
headCommits = ListField(child=ReleaseHeadCommitSerializer(), required=False)
51+
headCommits = ListField(child=ReleaseHeadCommitSerializerDeprecated(), required=False)
52+
refs = ListField(child=ReleaseHeadCommitSerializer(), required=False)
5153

5254

5355
class OrganizationReleaseDetailsEndpoint(OrganizationReleasesBaseEndpoint):
@@ -101,6 +103,17 @@ def put(self, request, organization, version):
101103
:param datetime dateReleased: an optional date that indicates when
102104
the release went live. If not provided
103105
the current time is assumed.
106+
:param array commits: an optional list of commit data to be associated
107+
with the release. Commits must include parameters
108+
``id`` (the sha of the commit), and can optionally
109+
include ``repository``, ``message``, ``author_name``,
110+
``author_email``, and ``timestamp``.
111+
:param array refs: an optional way to indicate the start and end commits
112+
for each repository included in a release. Head commits
113+
must include parameters ``repository`` and ``commit``
114+
(the HEAD sha). They can optionally include ``previousCommit``
115+
(the sha of the HEAD of the previous release), which should
116+
be specified if this is the first time you've sent commit data.
104117
:auth: required
105118
"""
106119
try:
@@ -141,10 +154,16 @@ def put(self, request, organization, version):
141154
# TODO(dcramer): handle errors with release payloads
142155
release.set_commits(commit_list)
143156

144-
head_commits = result.get('headCommits')
145-
if head_commits:
157+
refs = result.get('refs')
158+
if not refs:
159+
refs = [{
160+
'repository': r['repository'],
161+
'previousCommit': r.get('previousId'),
162+
'commit': r['currentId'],
163+
} for r in result.get('headCommits', [])]
164+
if refs:
146165
fetch_commits = request.user.is_authenticated() and not commit_list
147-
release.set_head_commits(head_commits, request.user, fetch_commits=fetch_commits)
166+
release.set_refs(refs, request.user, fetch_commits=fetch_commits)
148167

149168
if (not was_released and release.date_released):
150169
for project in release.projects.all():

src/sentry/api/endpoints/organization_releases.py

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
from sentry.api.bases.organization import OrganizationReleasesBaseEndpoint
1010
from sentry.api.paginator import OffsetPaginator
1111
from sentry.api.serializers import serialize
12-
from sentry.api.serializers.rest_framework import ReleaseHeadCommitSerializer, ListField
12+
from sentry.api.serializers.rest_framework import (
13+
ReleaseHeadCommitSerializer, ReleaseHeadCommitSerializerDeprecated, ListField
14+
)
1315
from sentry.models import Activity, Release
1416
from sentry.utils.apidocs import scenario, attach_scenarios
1517

@@ -37,7 +39,8 @@ def list_org_releases_scenario(runner):
3739

3840
class ReleaseSerializerWithProjects(ReleaseSerializer):
3941
projects = ListField()
40-
headCommits = ListField(child=ReleaseHeadCommitSerializer(), required=False)
42+
headCommits = ListField(child=ReleaseHeadCommitSerializerDeprecated(), required=False)
43+
refs = ListField(child=ReleaseHeadCommitSerializer(), required=False)
4144

4245

4346
class OrganizationReleasesEndpoint(OrganizationReleasesBaseEndpoint):
@@ -111,12 +114,12 @@ def post(self, request, organization):
111114
``id`` (the sha of the commit), and can optionally
112115
include ``repository``, ``message``, ``author_name``,
113116
``author_email``, and ``timestamp``.
114-
:param array headCommits: an optional way to indicate the start and end commits
115-
for each repository included in a release. Head commits
116-
must include parameters ``repository`` and ``currentId``
117-
(the HEAD sha). They can optionally include ``previousId``
118-
(the sha of the HEAD of the previous release), which should
119-
be specified if this is the first time you've sent commit data.
117+
:param array refs: an optional way to indicate the start and end commits
118+
for each repository included in a release. Head commits
119+
must include parameters ``repository`` and ``commit``
120+
(the HEAD sha). They can optionally include ``previousCommit``
121+
(the sha of the HEAD of the previous release), which should
122+
be specified if this is the first time you've sent commit data.
120123
:auth: required
121124
"""
122125
serializer = ReleaseSerializerWithProjects(data=request.DATA)
@@ -173,10 +176,16 @@ def post(self, request, organization):
173176
if commit_list:
174177
release.set_commits(commit_list)
175178

176-
head_commits = result.get('headCommits')
177-
if head_commits:
179+
refs = result.get('refs')
180+
if not refs:
181+
refs = [{
182+
'repository': r['repository'],
183+
'previousCommit': r.get('previousId'),
184+
'commit': r['currentId'],
185+
} for r in result.get('headCommits', [])]
186+
if refs:
178187
fetch_commits = request.user.is_authenticated() and not commit_list
179-
release.set_head_commits(head_commits, request.user, fetch_commits=fetch_commits)
188+
release.set_refs(refs, request.user, fetch_commits=fetch_commits)
180189

181190
if not created and not new_projects:
182191
# This is the closest status code that makes sense, and we want

src/sentry/api/serializers/rest_framework/release_head_commit.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@
33
from rest_framework import serializers
44

55

6-
class ReleaseHeadCommitSerializer(serializers.Serializer):
6+
class ReleaseHeadCommitSerializerDeprecated(serializers.Serializer):
77
currentId = serializers.CharField(max_length=64)
88
repository = serializers.CharField(max_length=64)
99
previousId = serializers.CharField(max_length=64, required=False)
10+
11+
12+
class ReleaseHeadCommitSerializer(serializers.Serializer):
13+
commit = serializers.CharField(max_length=64)
14+
repository = serializers.CharField(max_length=64)
15+
previousCommit = serializers.CharField(max_length=64, required=False)

src/sentry/models/release.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ def add_project(self, project):
219219
else:
220220
return True
221221

222-
def set_head_commits(self, head_commits, user, fetch_commits=False):
222+
def set_refs(self, refs, user, fetch_commits=False):
223223
from sentry.models import Commit, ReleaseHeadCommit, Repository
224224
from sentry.plugins import bindings
225225

@@ -230,19 +230,19 @@ def set_head_commits(self, head_commits, user, fetch_commits=False):
230230

231231
commit_list = []
232232

233-
for head_commit in head_commits:
233+
for ref in refs:
234234
try:
235235
repo = Repository.objects.get(
236236
organization_id=self.organization_id,
237-
name=head_commit['repository'],
237+
name=ref['repository'],
238238
)
239239
except Repository.DoesNotExist:
240240
continue
241241

242242
commit = Commit.objects.get_or_create(
243243
organization_id=self.organization_id,
244244
repository_id=repo.id,
245-
key=head_commit['currentId'],
245+
key=ref['commit'],
246246
)[0]
247247
# update head commit for repo/release if exists
248248
ReleaseHeadCommit.objects.create_or_update(
@@ -261,8 +261,8 @@ def set_head_commits(self, head_commits, user, fetch_commits=False):
261261

262262
# if previous commit isn't provided, try to get from
263263
# previous release otherwise, give up
264-
if head_commit.get('previousId'):
265-
start_sha = head_commit['previousId']
264+
if ref.get('previousCommit'):
265+
start_sha = ref['previousCommit']
266266
elif prev_release:
267267
try:
268268
start_sha = Commit.objects.filter(

tests/sentry/api/endpoints/test_organization_release_details.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,90 @@ def test_simple(self):
132132

133133
self.login_as(user=user)
134134

135+
url = reverse('sentry-api-0-organization-release-details', kwargs={
136+
'organization_slug': org.slug,
137+
'version': release.version,
138+
})
139+
response = self.client.put(url, {
140+
'ref': 'master',
141+
'refs': [
142+
{'commit': 'a' * 40, 'repository': repo.name},
143+
{'commit': 'b' * 40, 'repository': repo2.name},
144+
],
145+
})
146+
147+
assert response.status_code == 200, response.content
148+
assert response.data['version'] == release.version
149+
assert ReleaseCommit.objects.filter(
150+
commit__repository_id=repo.id,
151+
commit__key='62de626b7c7cfb8e77efb4273b1a3df4123e6216',
152+
release__version=response.data['version'],
153+
).exists()
154+
assert ReleaseCommit.objects.filter(
155+
commit__repository_id=repo.id,
156+
commit__key='58de626b7c7cfb8e77efb4273b1a3df4123e6345',
157+
release__version=response.data['version'],
158+
).exists()
159+
assert ReleaseCommit.objects.filter(
160+
commit__repository_id=repo2.id,
161+
commit__key='62de626b7c7cfb8e77efb4273b1a3df4123e6216',
162+
release__version=response.data['version'],
163+
).exists()
164+
assert ReleaseCommit.objects.filter(
165+
commit__repository_id=repo2.id,
166+
commit__key='58de626b7c7cfb8e77efb4273b1a3df4123e6345',
167+
release__version=response.data['version'],
168+
).exists()
169+
170+
release = Release.objects.get(id=release.id)
171+
assert release.ref == 'master'
172+
173+
# no access
174+
url = reverse('sentry-api-0-organization-release-details', kwargs={
175+
'organization_slug': org.slug,
176+
'version': release2.version,
177+
})
178+
response = self.client.put(url, {'ref': 'master'})
179+
assert response.status_code == 403
180+
181+
def test_deprecated_head_commits(self):
182+
user = self.create_user(is_staff=False, is_superuser=False)
183+
org = self.organization
184+
org.flags.allow_joinleave = False
185+
org.save()
186+
187+
repo = Repository.objects.create(
188+
organization_id=org.id,
189+
name='example/example',
190+
provider='dummy',
191+
)
192+
repo2 = Repository.objects.create(
193+
organization_id=org.id,
194+
name='example/example2',
195+
provider='dummy',
196+
)
197+
198+
team1 = self.create_team(organization=org)
199+
team2 = self.create_team(organization=org)
200+
201+
project = self.create_project(team=team1, organization=org)
202+
project2 = self.create_project(team=team2, organization=org)
203+
204+
release = Release.objects.create(
205+
organization_id=org.id,
206+
version='abcabcabc',
207+
)
208+
release2 = Release.objects.create(
209+
organization_id=org.id,
210+
version='12345678',
211+
)
212+
release.add_project(project)
213+
release2.add_project(project2)
214+
215+
self.create_member(teams=[team1], user=user, organization=org)
216+
217+
self.login_as(user=user)
218+
135219
url = reverse('sentry-api-0-organization-release-details', kwargs={
136220
'organization_slug': org.slug,
137221
'version': release.version,

tests/sentry/api/endpoints/test_organization_releases.py

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,67 @@ def test_commits_from_provider(self):
464464
self.create_member(teams=[team], user=user, organization=org)
465465
self.login_as(user=user)
466466

467+
url = reverse('sentry-api-0-organization-releases', kwargs={
468+
'organization_slug': org.slug
469+
})
470+
response = self.client.post(url, data={
471+
'version': '1.2.1',
472+
'refs': [
473+
{'commit': 'a' * 40, 'repository': repo.name},
474+
{'commit': 'b' * 40, 'repository': repo2.name},
475+
],
476+
'projects': [project.slug]
477+
})
478+
assert response.status_code == 201
479+
# check fake commits from dummy repo provider were created
480+
assert ReleaseCommit.objects.filter(
481+
commit__repository_id=repo.id,
482+
commit__key='62de626b7c7cfb8e77efb4273b1a3df4123e6216',
483+
release__version=response.data['version'],
484+
).exists()
485+
assert ReleaseCommit.objects.filter(
486+
commit__repository_id=repo.id,
487+
commit__key='58de626b7c7cfb8e77efb4273b1a3df4123e6345',
488+
release__version=response.data['version'],
489+
).exists()
490+
assert ReleaseCommit.objects.filter(
491+
commit__repository_id=repo2.id,
492+
commit__key='62de626b7c7cfb8e77efb4273b1a3df4123e6216',
493+
release__version=response.data['version'],
494+
).exists()
495+
assert ReleaseCommit.objects.filter(
496+
commit__repository_id=repo2.id,
497+
commit__key='58de626b7c7cfb8e77efb4273b1a3df4123e6345',
498+
release__version=response.data['version'],
499+
).exists()
500+
501+
def test_commits_from_provider_deprecated_head_commits(self):
502+
user = self.create_user(is_staff=False, is_superuser=False)
503+
org = self.create_organization()
504+
org.flags.allow_joinleave = False
505+
org.save()
506+
507+
repo = Repository.objects.create(
508+
organization_id=org.id,
509+
name='example/example',
510+
provider='dummy',
511+
)
512+
repo2 = Repository.objects.create(
513+
organization_id=org.id,
514+
name='example/example2',
515+
provider='dummy',
516+
)
517+
518+
team = self.create_team(organization=org)
519+
project = self.create_project(
520+
name='foo',
521+
organization=org,
522+
team=team
523+
)
524+
525+
self.create_member(teams=[team], user=user, organization=org)
526+
self.login_as(user=user)
527+
467528
url = reverse('sentry-api-0-organization-releases', kwargs={
468529
'organization_slug': org.slug
469530
})
@@ -674,7 +735,7 @@ def test_api_token(self):
674735
response = self.client.post(url, data={
675736
'version': '1.2.1',
676737
'headCommits': [
677-
{'currentId': 'a' * 40, 'repository': repo.name},
738+
{'currentId': 'a' * 40, 'repository': repo.name, 'previousId': 'c' * 40},
678739
{'currentId': 'b' * 40, 'repository': repo2.name},
679740
],
680741
'projects': [project1.slug]

0 commit comments

Comments
 (0)