Skip to content
Draft
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
b3cd378
add build number sorting
srest2021 Nov 4, 2025
0eb0eca
ensure semver order test fails without build number ordering
srest2021 Nov 4, 2025
afac5b0
add compare_version test
srest2021 Nov 4, 2025
e479720
clean up test
srest2021 Nov 4, 2025
185a8a1
remove annotation
srest2021 Nov 5, 2025
b78407a
add lexicographic sort on build_code
srest2021 Nov 5, 2025
e9166d9
Merge branch 'master' into srest2021/REPLAY-803
srest2021 Nov 5, 2025
3096e53
make sure build code test doesnt pass by coincidence
srest2021 Nov 5, 2025
2ac040b
Merge branch 'master' into srest2021/REPLAY-803
srest2021 Nov 5, 2025
e3a53a7
add build_number_case annotation
srest2021 Nov 5, 2025
8328882
rename case column
srest2021 Nov 6, 2025
d3b19a0
rename case column
srest2021 Nov 6, 2025
4f987e8
fix
srest2021 Nov 6, 2025
ce127dc
missed some renaming
srest2021 Nov 6, 2025
2d46a94
Merge branch 'master' into srest2021/REPLAY-803
srest2021 Nov 6, 2025
8d23660
fix typing
srest2021 Nov 6, 2025
354b7f2
add feature flag
srest2021 Nov 7, 2025
63b9dab
dont need to update ordering in this file
srest2021 Nov 10, 2025
b381471
more tests
srest2021 Nov 10, 2025
f35d7b0
more tests
srest2021 Nov 10, 2025
83a2701
cleaning up
srest2021 Nov 10, 2025
cc73245
more tests & clean up feature flag checks
srest2021 Nov 10, 2025
ffdaf0d
remove unnecessary sorting in backend.py; update filter aliases
srest2021 Nov 10, 2025
7c2ce34
Merge branch 'master' into srest2021/REPLAY-803
srest2021 Nov 10, 2025
22ae3bf
fix flaky test
srest2021 Nov 10, 2025
30cc2d9
fix typing
srest2021 Nov 10, 2025
d07da24
small naming change
srest2021 Nov 10, 2025
960111e
update utils
srest2021 Nov 10, 2025
ba16113
fix failing test
srest2021 Nov 10, 2025
de556e9
Merge branch 'master' into srest2021/REPLAY-803
srest2021 Nov 10, 2025
3486a98
fix typing again
srest2021 Nov 10, 2025
496d672
Merge branch 'master' into srest2021/REPLAY-803
srest2021 Nov 11, 2025
205504e
revert filter changes
srest2021 Nov 11, 2025
22984f1
oops
srest2021 Nov 11, 2025
c77a856
revert backend.py changes
srest2021 Nov 11, 2025
0c479bc
latest adopted release test
srest2021 Nov 12, 2025
2751910
fix comment
srest2021 Nov 12, 2025
f7cb5dc
more test coverage for latest adopted release
srest2021 Nov 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion src/sentry/models/release.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,16 @@ class Meta:

__repr__ = sane_repr("organization_id", "version")

SEMVER_COLS = ["major", "minor", "patch", "revision", "prerelease_case", "prerelease"]
SEMVER_COLS = [
"major",
"minor",
"patch",
"revision",
"prerelease_case",
"prerelease",
"build_number",
"build_code",
]

def __eq__(self, other: object) -> bool:
"""Make sure that specialized releases are only comparable to the same
Expand Down Expand Up @@ -398,6 +407,8 @@ def semver_tuple(self) -> SemverVersion:
self.revision,
1 if self.prerelease == "" else 0,
self.prerelease,
self.build_number,
self.build_code,
)

@classmethod
Expand Down
5 changes: 4 additions & 1 deletion src/sentry/models/releases/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@


class SemverVersion(
namedtuple("SemverVersion", "major minor patch revision prerelease_case prerelease")
namedtuple(
"SemverVersion",
"major minor patch revision prerelease_case prerelease build_number build_code",
)
):
pass

Expand Down
10 changes: 7 additions & 3 deletions tests/sentry/api/endpoints/test_organization_releases.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,21 +249,25 @@ def test_release_list_order_by_build_number(self) -> None:
def test_release_list_order_by_semver(self) -> None:
self.login_as(user=self.user)
release_1 = self.create_release(version="[email protected]")
release_2 = self.create_release(version="[email protected]+122")
Copy link
Member Author

@srest2021 srest2021 Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switch the order in which release_2 and release_7 are created so the build_number sorting doesn't coincidentally pass due to insertion order.

release_2 = self.create_release(version="[email protected]+123")
release_3 = self.create_release(version="[email protected]")
release_4 = self.create_release(version="[email protected]")
release_5 = self.create_release(version="[email protected]")
release_6 = self.create_release(version="[email protected]")
release_7 = self.create_release(version="[email protected]+123")
release_7 = self.create_release(version="[email protected]+122")
release_8 = self.create_release(version="test@some_thing")
release_9 = self.create_release(version="random_junk")
release_10 = self.create_release(version="[email protected]+abc")
release_11 = self.create_release(version="[email protected]+xyz")

response = self.get_success_response(self.organization.slug, sort="semver")
self.assert_expected_versions(
response,
[
release_7,
release_2,
release_7,
release_11,
release_10,
release_6,
release_5,
release_4,
Expand Down
31 changes: 31 additions & 0 deletions tests/sentry/models/test_release.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import pytest
from django.core.exceptions import ValidationError
from django.utils import timezone
from sentry_relay.processing import compare_version, parse_release

from sentry.api.exceptions import InvalidRepository
from sentry.api.release_search import INVALID_SEMVER_MESSAGE
Expand Down Expand Up @@ -1903,3 +1904,33 @@ def test_get_unused_filter_allows_cleanup_with_old_group_resolutions(self):
unused_filter = Release.get_unused_filter(self.cutoff_date)
unused_releases = Release.objects.filter(unused_filter)
assert old_release in unused_releases


class ReleaseOrderBySemverTestCase(TestCase):
def test_compare_version_sorts_by_build_number(self):
"""Test that compare_version correctly sorts releases by build number with various formats"""

# numeric builds (numerical comparison)
v1 = parse_release("[email protected]+999")["version_raw"]
v2 = parse_release("[email protected]+1000")["version_raw"]
assert compare_version(v1, v2) == -1
assert compare_version(v2, v1) == 1

# alphanumeric builds (lexicographic comparison)
v1 = parse_release("[email protected]+abc")["version_raw"]
v2 = parse_release("[email protected]+xyz")["version_raw"]
assert compare_version(v1, v2) == -1
assert compare_version(v2, v1) == 1
v1 = parse_release("[email protected]+z1b2c3d")["version_raw"]
v2 = parse_release("[email protected]+z9y8x7w")["version_raw"]
assert compare_version(v1, v2) == -1
assert compare_version(v2, v1) == 1
v1 = parse_release("[email protected]+build.45")["version_raw"]
v2 = parse_release("[email protected]+build.123")["version_raw"]
assert compare_version(v1, v2) == 1
assert compare_version(v2, v1) == -1

# no build vs. with build (with build > no build)
v_no_build = parse_release("[email protected]")["version_raw"]
v_with_build = parse_release("[email protected]+123")["version_raw"]
assert compare_version(v_no_build, v_with_build) == -1
Loading