Skip to content
Open
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
1 change: 1 addition & 0 deletions src/sentry/preprod/vcs/pr_comments/snapshot_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ def create_preprod_snapshot_pr_comment_task(
base_artifact_map,
changes_map,
approvals_map=approvals_map,
project=artifact.project,
)

existing_comment_id = find_existing_comment_id(all_for_pr, "snapshots")
Expand Down
12 changes: 11 additions & 1 deletion src/sentry/preprod/vcs/pr_comments/snapshot_templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from django.utils.translation import gettext_lazy as _

from sentry.models.project import Project
from sentry.preprod.models import PreprodArtifact, PreprodComparisonApproval
from sentry.preprod.snapshots.models import PreprodSnapshotComparison, PreprodSnapshotMetrics
from sentry.preprod.url_utils import get_preprod_artifact_comparison_url, get_preprod_artifact_url
Expand All @@ -21,6 +22,8 @@ def format_snapshot_pr_comment(
base_artifact_map: dict[int, PreprodArtifact],
changes_map: dict[int, bool],
approvals_map: dict[int, PreprodComparisonApproval] | None = None,
*,
project: Project,
) -> str:
"""Format a PR comment for snapshot comparisons."""
if not artifacts:
Expand Down Expand Up @@ -86,7 +89,14 @@ def format_snapshot_pr_comment(
f" | {status} |"
)

return f"{_HEADER}\n\n{COMPARISON_TABLE_HEADER}" + "\n".join(table_rows)
settings_url = project.organization.absolute_url(
f"/settings/projects/{project.slug}/mobile-builds/", query="tab=snapshots"
)

table = f"{_HEADER}\n\n{COMPARISON_TABLE_HEADER}" + "\n".join(table_rows)
settings_link = f"[⚙️ {project.name} Snapshot Settings]({settings_url})"

return f"{table}\n\n{settings_link}"


def _name_cell(
Expand Down
42 changes: 36 additions & 6 deletions tests/sentry/preprod/vcs/pr_comments/test_snapshot_templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def _create_approval(self, artifact: PreprodArtifact) -> PreprodComparisonApprov
class FormatSnapshotPrCommentEmptyTest(SnapshotPrCommentTestBase):
def test_empty_artifacts_raises(self) -> None:
with pytest.raises(ValueError, match="Cannot format PR comment for empty artifact list"):
format_snapshot_pr_comment([], {}, {}, {}, {})
format_snapshot_pr_comment([], {}, {}, {}, {}, project=self.project)


@cell_silo_test
Expand All @@ -87,7 +87,7 @@ def test_no_metrics_shows_processing(self) -> None:
app_id="com.example.app",
)

result = format_snapshot_pr_comment([artifact], {}, {}, {}, {})
result = format_snapshot_pr_comment([artifact], {}, {}, {}, {}, project=self.project)

assert "## Sentry Snapshot Testing" in result
assert "Processing" in result
Expand All @@ -103,6 +103,7 @@ def test_no_comparison_with_base_shows_processing(self) -> None:
{},
{head_artifact.id: base_artifact},
{},
project=self.project,
)

assert "Processing" in result
Expand All @@ -121,6 +122,7 @@ def test_pending_comparison_shows_processing(self) -> None:
{head_metrics.id: comparison},
{head_artifact.id: base_artifact},
{},
project=self.project,
)

assert "Processing" in result
Expand All @@ -139,6 +141,7 @@ def test_processing_comparison_shows_processing(self) -> None:
{head_metrics.id: comparison},
{head_artifact.id: base_artifact},
{},
project=self.project,
)

assert "Processing" in result
Expand All @@ -160,6 +163,7 @@ def test_failed_comparison_shows_failure(self) -> None:
{head_metrics.id: comparison},
{head_artifact.id: base_artifact},
{},
project=self.project,
)

assert "Comparison failed" in result
Expand Down Expand Up @@ -189,6 +193,7 @@ def test_no_changes_shows_unchanged(self) -> None:
{head_metrics.id: comparison},
{head_artifact.id: base_artifact},
{},
project=self.project,
)

assert "## Sentry Snapshot Testing" in result
Expand Down Expand Up @@ -219,6 +224,7 @@ def test_changes_show_needs_approval(self) -> None:
{head_metrics.id: comparison},
{head_artifact.id: base_artifact},
{head_artifact.id: True},
project=self.project,
)

assert "Needs approval" in result
Expand Down Expand Up @@ -246,6 +252,7 @@ def test_approved_shows_approved_status(self) -> None:
{head_artifact.id: base_artifact},
{head_artifact.id: True},
approvals_map={head_artifact.id: approval},
project=self.project,
)

assert "Approved" in result
Expand Down Expand Up @@ -277,6 +284,7 @@ def test_multiple_artifacts(self) -> None:
comparisons_map,
base_artifact_map,
{},
project=self.project,
)

for i in range(3):
Expand All @@ -299,6 +307,7 @@ def test_section_links_include_artifact_url(self) -> None:
{head_metrics.id: comparison},
{head_artifact.id: base_artifact},
{head_artifact.id: True},
project=self.project,
)

assert f"/preprod/snapshots/{head_artifact.id}" in result
Expand All @@ -323,6 +332,7 @@ def test_zero_counts_are_not_linked(self) -> None:
{head_metrics.id: comparison},
{head_artifact.id: base_artifact},
{},
project=self.project,
)

assert "?section=" not in result
Expand All @@ -339,17 +349,31 @@ def test_table_header_present(self) -> None:
{head_metrics.id: comparison},
{},
{},
project=self.project,
)

assert "| Name | Added | Removed | Modified | Renamed | Unchanged | Status |" in result

def test_settings_link_included(self) -> None:
artifact, metrics = self._create_artifact_with_metrics()

result = format_snapshot_pr_comment(
[artifact], {artifact.id: metrics}, {}, {}, {}, project=self.project
)

assert f"/settings/projects/{self.project.slug}/mobile-builds/" in result
assert "tab=snapshots" in result
assert f"{self.project.name} Snapshot Settings" in result


@cell_silo_test
class FormatSnapshotPrCommentNoBaseTest(SnapshotPrCommentTestBase):
def test_no_base_shows_uploaded_with_count(self) -> None:
artifact, metrics = self._create_artifact_with_metrics(app_name="My App", image_count=15)

result = format_snapshot_pr_comment([artifact], {artifact.id: metrics}, {}, {}, {})
result = format_snapshot_pr_comment(
[artifact], {artifact.id: metrics}, {}, {}, {}, project=self.project
)

assert "## Sentry Snapshot Testing" in result
assert "15 uploaded" in result
Expand All @@ -359,7 +383,9 @@ def test_no_base_shows_uploaded_with_count(self) -> None:
def test_no_base_uses_same_table_header(self) -> None:
artifact, metrics = self._create_artifact_with_metrics()

result = format_snapshot_pr_comment([artifact], {artifact.id: metrics}, {}, {}, {})
result = format_snapshot_pr_comment(
[artifact], {artifact.id: metrics}, {}, {}, {}, project=self.project
)

assert "| Name | Added | Removed | Modified | Renamed | Unchanged | Status |" in result

Expand All @@ -374,7 +400,9 @@ def test_no_base_multiple_artifacts(self) -> None:
artifacts.append(artifact)
metrics_map[artifact.id] = metrics

result = format_snapshot_pr_comment(artifacts, metrics_map, {}, {}, {})
result = format_snapshot_pr_comment(
artifacts, metrics_map, {}, {}, {}, project=self.project
)

assert "com.example.app0" in result
assert "com.example.app1" in result
Expand All @@ -384,6 +412,8 @@ def test_no_base_multiple_artifacts(self) -> None:
def test_no_base_app_id_shown(self) -> None:
artifact, metrics = self._create_artifact_with_metrics(app_id="com.example.myapp")

result = format_snapshot_pr_comment([artifact], {artifact.id: metrics}, {}, {}, {})
result = format_snapshot_pr_comment(
[artifact], {artifact.id: metrics}, {}, {}, {}, project=self.project
)

assert "`com.example.myapp`" in result
Loading