Skip to content

Commit

Permalink
feat(releases): Clear the commits associated to a release (#28831)
Browse files Browse the repository at this point in the history
Objective:
This PR creates a new clear_commits method on the Release model to delete the associated ReleaseCommits and ReleaseHeadCommit and reset the commit related metadata for the release. We will not delete the rows in the Commit table because they may be used for another release.
  • Loading branch information
NisanthanNanthakumar authored Oct 4, 2021
1 parent e66ec0c commit bf6292e
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 8 deletions.
23 changes: 15 additions & 8 deletions src/sentry/api/endpoints/organization_release_details.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,14 +453,21 @@ def put(self, request, organization, version):

refs = result.get("refs")
if not refs:
refs = [
{
"repository": r["repository"],
"previousCommit": r.get("previousId"),
"commit": r["currentId"],
}
for r in result.get("headCommits", [])
]
# Handle legacy
if result.get("headCommits", []):
refs = [
{
"repository": r["repository"],
"previousCommit": r.get("previousId"),
"commit": r["currentId"],
}
for r in result.get("headCommits", [])
]
# Clear commits in release
else:
if result.get("refs") == []:
release.clear_commits()

scope.set_tag("has_refs", bool(refs))
if refs:
if not request.user.is_authenticated:
Expand Down
19 changes: 19 additions & 0 deletions src/sentry/models/release.py
Original file line number Diff line number Diff line change
Expand Up @@ -1079,6 +1079,25 @@ def count_artifacts(self):
counts = get_artifact_counts([self.id])
return counts.get(self.id, 0)

def clear_commits(self):
"""
Delete all release-specific commit data associated to this release. We will not delete the Commit model values because other releases may use these commits.
"""
with sentry_sdk.start_span(op="clear_commits"):
from sentry.models import ReleaseCommit, ReleaseHeadCommit

ReleaseHeadCommit.objects.get(
organization_id=self.organization_id, release=self
).delete()
ReleaseCommit.objects.filter(
organization_id=self.organization_id, release=self
).delete()

self.authors = []
self.commit_count = 0
self.last_commit_id = None
self.save()


def get_artifact_counts(release_ids: List[int]) -> Mapping[int, int]:
"""Get artifact count grouped by IDs"""
Expand Down
74 changes: 74 additions & 0 deletions tests/sentry/models/test_release.py
Original file line number Diff line number Diff line change
Expand Up @@ -1204,3 +1204,77 @@ def test_follows_semver_check_when_project_only_has_two_releases(self):
)
is False
)


class ClearCommitsTestCase(TestCase):
def test_simple(self):
org = self.create_organization()
project = self.create_project(organization=org, name="foo")
group = self.create_group(project=project)

repo = Repository.objects.create(organization_id=org.id, name="test/repo")

author = CommitAuthor.objects.create(
name="foo bar baz", email="foo@example.com", organization_id=org.id
)

author2 = CommitAuthor.objects.create(
name="foo bar boo", email="baroo@example.com", organization_id=org.id
)

commit = Commit.objects.create(
organization_id=org.id,
repository_id=repo.id,
author=author,
date_added="2019-03-01 12:00:00",
message="fixes %s" % (group.qualified_short_id),
key="alksdflskdfjsldkfajsflkslk",
)
commit2 = Commit.objects.create(
organization_id=org.id,
repository_id=repo.id,
author=author2,
date_added="2019-03-01 12:02:00",
message="i fixed something",
key="lskfslknsdkcsnlkdflksfdkls",
)

release = Release.objects.create(version="abcdabc", organization=org)
release.add_project(project)
release.set_commits(
[
{"id": commit.key, "repository": repo.name},
{"id": commit2.key, "repository": repo.name},
]
)
# Confirm setup works
assert ReleaseCommit.objects.filter(commit=commit, release=release).exists()
assert ReleaseCommit.objects.filter(commit=commit2, release=release).exists()

assert release.commit_count == 2
assert release.authors == [str(author.id), str(author2.id)]
assert release.last_commit_id == commit.id

assert ReleaseHeadCommit.objects.filter(
release_id=release.id, commit_id=commit.id, repository_id=repo.id
).exists()

# Now clear the release;
release.clear_commits()
assert not ReleaseCommit.objects.filter(commit=commit, release=release).exists()
assert not ReleaseCommit.objects.filter(commit=commit2, release=release).exists()
assert not ReleaseHeadCommit.objects.filter(
release_id=release.id, commit_id=commit.id, repository_id=repo.id
).exists()

assert release.commit_count == 0
assert release.authors == []
assert not release.last_commit_id

# Commits should still exist
assert Commit.objects.filter(
id=commit.id, organization_id=org.id, repository_id=repo.id
).exists()
assert Commit.objects.filter(
id=commit2.id, organization_id=org.id, repository_id=repo.id
).exists()

0 comments on commit bf6292e

Please sign in to comment.