Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -343,13 +343,39 @@ def post(
head_size_analysis__in=head_size_metrics,
base_size_analysis__in=base_size_metrics,
)
is_rerun = request.query_params.get("rerun") == "true"

if existing_comparisons.exists():
if is_active_superuser(request) or is_active_staff(request):
if is_rerun:
if is_active_superuser(request) or is_active_staff(request):
comparisons_deleted, files_deleted = _delete_existing_comparisons(
existing_comparisons
)
logger.info(
"preprod.size_analysis.compare.api.post.rerun_deleted_existing",
extra={
"head_artifact_id": head_artifact.id,
"base_artifact_id": base_artifact.id,
"comparisons_deleted": comparisons_deleted,
"files_deleted": files_deleted,
"user_id": request.user.id,
},
)
elif request.user.is_staff:
raise StaffRequired
else:
return Response({"detail": "Only staff can rerun comparisons."}, status=403)
elif (
existing_comparisons.filter(
state=PreprodArtifactSizeComparison.State.FAILED
).count()
== existing_comparisons.count()
):
comparisons_deleted, files_deleted = _delete_existing_comparisons(
existing_comparisons
)
logger.info(
"preprod.size_analysis.compare.api.post.rerun_deleted_existing",
"preprod.size_analysis.compare.api.post.retry_deleted_failed",
extra={
"head_artifact_id": head_artifact.id,
"base_artifact_id": base_artifact.id,
Expand All @@ -358,8 +384,6 @@ def post(
"user_id": request.user.id,
},
)
elif request.user.is_staff:
raise StaffRequired
else:
comparison_models = []
for comparison in existing_comparisons:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export default function BuildComparison() {
RequestError
>({
mutationFn: () => {
return fetchMutation({url: compareUrl, method: 'POST'});
return fetchMutation({url: `${compareUrl}?rerun=true`, method: 'POST'});
},
onSuccess: response => {
if (response?.status === 'exists') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -600,10 +600,12 @@ def test_post_comparison_existing_comparison(self) -> None:
assert data["comparisons"][0]["comparison_id"] == comparison.id

@override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_post_comparison_existing_failed_comparison(self) -> None:
"""Test POST endpoint returns existing failed comparison when comparison exists and failed"""
# Create a failed comparison
comparison = self.create_preprod_artifact_size_comparison(
@patch("sentry.preprod.size_analysis.tasks.manual_size_analysis_comparison.apply_async")
def test_post_comparison_existing_failed_comparison_auto_retries(
self, mock_apply_async
) -> None:
"""Test POST endpoint auto-retries when all existing comparisons are failed"""
self.create_preprod_artifact_size_comparison(
head_size_analysis=self.head_size_metric,
base_size_analysis=self.base_size_metric,
organization=self.organization,
Expand All @@ -616,12 +618,13 @@ def test_post_comparison_existing_failed_comparison(self) -> None:

assert response.status_code == 200
data = response.json()
assert data["status"] == "exists"
assert data["status"] == "created"
assert len(data["comparisons"]) == 1
comparison_data = data["comparisons"][0]
assert comparison_data["state"] == comparison.state
assert comparison_data["error_code"] == str(comparison.error_code)
assert comparison_data["error_message"] == comparison.error_message
assert comparison_data["state"] == PreprodArtifactSizeComparison.State.PENDING
assert comparison_data["comparison_id"] is None

mock_apply_async.assert_called_once()

@override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_post_comparison_cannot_compare_size_metrics(self) -> None:
Expand Down Expand Up @@ -804,3 +807,68 @@ def test_get_returns_404_for_expired_base_artifact(self, mock_cutoff):
)
assert response.status_code == 404
assert response.data["detail"] == "This build's size data has expired."

@override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
@patch("sentry.preprod.size_analysis.tasks.manual_size_analysis_comparison.apply_async")
def test_post_rerun_as_staff_deletes_and_recreates(self, mock_apply_async):
"""Test POST with rerun=true as active staff deletes existing and creates new comparisons"""
self.create_preprod_artifact_size_comparison(
head_size_analysis=self.head_size_metric,
base_size_analysis=self.base_size_metric,
organization=self.organization,
state=PreprodArtifactSizeComparison.State.SUCCESS,
file_id=12345,
)

staff_user = self.create_user(is_staff=True)
self.organization.member_set.create(user_id=staff_user.id)
self.login_as(user=staff_user)

with patch(
"sentry.preprod.api.endpoints.size_analysis.project_preprod_size_analysis_compare.is_active_staff",
return_value=True,
):
response = self.client.post(f"{self._get_url()}?rerun=true")

assert response.status_code == 200
data = response.json()
assert data["status"] == "created"
assert len(data["comparisons"]) == 1
assert data["comparisons"][0]["state"] == PreprodArtifactSizeComparison.State.PENDING
mock_apply_async.assert_called_once()

@override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_post_rerun_as_non_staff_returns_403(self):
"""Test POST with rerun=true as non-staff returns 403"""
self.create_preprod_artifact_size_comparison(
head_size_analysis=self.head_size_metric,
base_size_analysis=self.base_size_metric,
organization=self.organization,
state=PreprodArtifactSizeComparison.State.SUCCESS,
file_id=12345,
)

response = self.client.post(f"{self._get_url()}?rerun=true")

assert response.status_code == 403
assert response.json()["detail"] == "Only staff can rerun comparisons."

@override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_post_rerun_as_inactive_staff_raises_staff_required(self):
"""Test POST with rerun=true as is_staff user without active staff session raises StaffRequired"""
self.create_preprod_artifact_size_comparison(
head_size_analysis=self.head_size_metric,
base_size_analysis=self.base_size_metric,
organization=self.organization,
state=PreprodArtifactSizeComparison.State.SUCCESS,
file_id=12345,
)

staff_user = self.create_user(is_staff=True)
self.organization.member_set.create(user_id=staff_user.id)
self.login_as(user=staff_user)

response = self.client.post(f"{self._get_url()}?rerun=true")

assert response.status_code == 403
assert response.json()["detail"]["code"] == "staff-required"
Loading