Skip to content

Commit 95d1c03

Browse files
authored
feat(preprod): skip comparisons for different analysis versions (#103195)
Resolves EME-629 For now this just handles skipping the treemap diff item comparisons, although we also spoke about perhaps skipping the diff altogether if the major versions differ.
1 parent 5d78c3a commit 95d1c03

File tree

3 files changed

+386
-58
lines changed

3 files changed

+386
-58
lines changed

src/sentry/preprod/size_analysis/compare.py

Lines changed: 115 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
import logging
44

5+
from packaging.version import InvalidVersion
6+
from packaging.version import parse as parse_version
7+
58
from sentry.preprod.models import PreprodArtifactSizeMetrics
69
from sentry.preprod.size_analysis.models import (
710
ComparisonResults,
@@ -21,7 +24,9 @@ def compare_size_analysis(
2124
base_size_analysis: PreprodArtifactSizeMetrics,
2225
base_size_analysis_results: SizeAnalysisResults,
2326
) -> ComparisonResults:
24-
diff_items = []
27+
skip_diff_item_comparison = _should_skip_diff_item_comparison(
28+
head_size_analysis_results, base_size_analysis_results
29+
)
2530

2631
head_treemap = (
2732
head_size_analysis_results.treemap.root if head_size_analysis_results.treemap else None
@@ -35,70 +40,82 @@ def compare_size_analysis(
3540

3641
all_paths = set(head_files.keys()) | set(base_files.keys())
3742

38-
for path in sorted(all_paths):
39-
head_elements = head_files.get(path, [])
40-
base_elements = base_files.get(path, [])
43+
diff_items = []
4144

42-
matched_pairs, unmatched_head, unmatched_base = _match_elements(
43-
head_elements, base_elements
44-
)
45+
if not skip_diff_item_comparison:
46+
for path in sorted(all_paths):
47+
head_elements = head_files.get(path, [])
48+
base_elements = base_files.get(path, [])
4549

46-
# Process matched pairs (modified or unchanged)
47-
for head_element, base_element in matched_pairs:
48-
head_size = head_element.size
49-
base_size = base_element.size
50-
size_diff = head_size - base_size
51-
52-
if size_diff == 0:
53-
continue # Skip items with no size change
54-
55-
item_type = head_element.type
56-
diff_type = DiffType.INCREASED if size_diff > 0 else DiffType.DECREASED
57-
58-
diff_items.append(
59-
DiffItem(
60-
size_diff=size_diff,
61-
head_size=head_size,
62-
base_size=base_size,
63-
path=path,
64-
item_type=item_type,
65-
type=diff_type,
66-
)
50+
matched_pairs, unmatched_head, unmatched_base = _match_elements(
51+
head_elements, base_elements
6752
)
6853

69-
# Process unmatched head elements (added)
70-
for head_element in unmatched_head:
71-
head_size = head_element.size
72-
if head_size == 0:
73-
continue
74-
75-
diff_items.append(
76-
DiffItem(
77-
size_diff=head_size,
78-
head_size=head_size,
79-
base_size=None,
80-
path=path,
81-
item_type=head_element.type,
82-
type=DiffType.ADDED,
54+
# Process matched pairs (modified or unchanged)
55+
for head_element, base_element in matched_pairs:
56+
head_size = head_element.size
57+
base_size = base_element.size
58+
size_diff = head_size - base_size
59+
60+
if size_diff == 0:
61+
continue # Skip items with no size change
62+
63+
item_type = head_element.type
64+
diff_type = DiffType.INCREASED if size_diff > 0 else DiffType.DECREASED
65+
66+
diff_items.append(
67+
DiffItem(
68+
size_diff=size_diff,
69+
head_size=head_size,
70+
base_size=base_size,
71+
path=path,
72+
item_type=item_type,
73+
type=diff_type,
74+
)
8375
)
84-
)
8576

86-
# Process unmatched base elements (removed)
87-
for base_element in unmatched_base:
88-
base_size = base_element.size
89-
if base_size == 0:
90-
continue
77+
# Process unmatched head elements (added)
78+
for head_element in unmatched_head:
79+
head_size = head_element.size
80+
if head_size == 0:
81+
continue
82+
83+
diff_items.append(
84+
DiffItem(
85+
size_diff=head_size,
86+
head_size=head_size,
87+
base_size=None,
88+
path=path,
89+
item_type=head_element.type,
90+
type=DiffType.ADDED,
91+
)
92+
)
9193

92-
diff_items.append(
93-
DiffItem(
94-
size_diff=-base_size,
95-
head_size=None,
96-
base_size=base_size,
97-
path=path,
98-
item_type=base_element.type,
99-
type=DiffType.REMOVED,
94+
# Process unmatched base elements (removed)
95+
for base_element in unmatched_base:
96+
base_size = base_element.size
97+
if base_size == 0:
98+
continue
99+
100+
diff_items.append(
101+
DiffItem(
102+
size_diff=-base_size,
103+
head_size=None,
104+
base_size=base_size,
105+
path=path,
106+
item_type=base_element.type,
107+
type=DiffType.REMOVED,
108+
)
100109
)
101-
)
110+
else:
111+
logger.info(
112+
"preprod.size_analysis.compare.skipped_diff_item_comparison",
113+
extra={
114+
"head_analysis_version": head_size_analysis_results.analysis_version,
115+
"base_analysis_version": base_size_analysis_results.analysis_version,
116+
"preprod_artifact_id": head_size_analysis.preprod_artifact_id,
117+
},
118+
)
102119

103120
size_metric_diff_item = SizeMetricDiffItem(
104121
metrics_artifact_type=head_size_analysis.metrics_artifact_type,
@@ -112,9 +129,50 @@ def compare_size_analysis(
112129
return ComparisonResults(
113130
diff_items=diff_items,
114131
size_metric_diff_item=size_metric_diff_item,
132+
skipped_diff_item_comparison=skip_diff_item_comparison,
133+
head_analysis_version=head_size_analysis_results.analysis_version,
134+
base_analysis_version=base_size_analysis_results.analysis_version,
115135
)
116136

117137

138+
def _should_skip_diff_item_comparison(
139+
head_size_analysis_results: SizeAnalysisResults,
140+
base_size_analysis_results: SizeAnalysisResults,
141+
) -> bool:
142+
head_version = None
143+
base_version = None
144+
145+
if head_size_analysis_results.analysis_version:
146+
try:
147+
head_version = parse_version(head_size_analysis_results.analysis_version)
148+
except InvalidVersion:
149+
logger.warning(
150+
"preprod.size_analysis.compare.invalid_version_format",
151+
extra={
152+
"analysis_version": head_size_analysis_results.analysis_version,
153+
},
154+
)
155+
156+
if base_size_analysis_results.analysis_version:
157+
try:
158+
base_version = parse_version(base_size_analysis_results.analysis_version)
159+
except InvalidVersion:
160+
logger.warning(
161+
"preprod.size_analysis.compare.invalid_version_format",
162+
extra={
163+
"analysis_version": base_size_analysis_results.analysis_version,
164+
},
165+
)
166+
167+
if not head_version or not base_version:
168+
return False
169+
170+
has_mismatched_major = head_version.major != base_version.major
171+
has_mismatched_minor = head_version.minor != base_version.minor
172+
173+
return has_mismatched_major or has_mismatched_minor
174+
175+
118176
def _match_elements(
119177
head_elements: list[TreemapElement], base_elements: list[TreemapElement]
120178
) -> tuple[list[tuple[TreemapElement, TreemapElement]], list[TreemapElement], list[TreemapElement]]:

src/sentry/preprod/size_analysis/models.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,6 @@ class SizeMetricDiffItem(BaseModel):
7373
class ComparisonResults(BaseModel):
7474
diff_items: list[DiffItem]
7575
size_metric_diff_item: SizeMetricDiffItem
76+
skipped_diff_item_comparison: bool
77+
head_analysis_version: str | None
78+
base_analysis_version: str | None

0 commit comments

Comments
 (0)