Skip to content

Commit 138af3b

Browse files
feat(attachments): Include all attachment with screenshot in name (#91602)
Currently, attachments considered as screenshots are very restrictive. This opens it up to any files containing `screenshot` in their name. This will be immediately useful to Native attachments, which name the files as `crash_screenshot.png`. Fixes #91430. --------- Co-authored-by: Bruno Garcia <[email protected]>
1 parent c77916b commit 138af3b

File tree

3 files changed

+41
-35
lines changed

3 files changed

+41
-35
lines changed

src/sentry/models/eventattachment.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,7 @@ def get_crashreport_key(group_id: int) -> str:
3434
def event_attachment_screenshot_filter(
3535
queryset: BaseQuerySet[EventAttachment],
3636
) -> BaseQuerySet[EventAttachment]:
37-
# Intentionally a hardcoded list instead of a regex since current usecases do not have more 3 screenshots
38-
return queryset.filter(
39-
name__in=[
40-
*[f"screenshot{f'-{i}' if i > 0 else ''}.jpg" for i in range(4)],
41-
*[f"screenshot{f'-{i}' if i > 0 else ''}.png" for i in range(4)],
42-
]
43-
)
37+
return queryset.filter(models.Q(name__icontains="screenshot"))
4438

4539

4640
@dataclass(frozen=True)

tests/sentry/api/endpoints/test_event_attachments.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -82,19 +82,26 @@ def test_is_screenshot(self):
8282
data={"fingerprint": ["group1"], "timestamp": min_ago}, project_id=self.project.id
8383
)
8484

85-
attachment1 = EventAttachment.objects.create(
85+
file = File.objects.create(name="screenshot.png", type="image/png")
86+
EventAttachment.objects.create(
87+
event_id=event1.event_id,
88+
project_id=event1.project_id,
89+
file_id=file.id,
90+
name=file.name,
91+
)
92+
file = File.objects.create(name="crash_screenshot.png")
93+
EventAttachment.objects.create(
8694
event_id=event1.event_id,
8795
project_id=event1.project_id,
88-
file_id=File.objects.create(name="screenshot.png", type="image/png").id,
89-
name="screenshot.png",
96+
file_id=file.id,
97+
name=file.name,
9098
)
91-
file = File.objects.create(name="screenshot-not.png", type="image/png")
99+
file = File.objects.create(name="foo.png")
92100
EventAttachment.objects.create(
93101
event_id=event1.event_id,
94102
project_id=event1.project_id,
95103
file_id=file.id,
96-
type=file.type,
97-
name="screenshot-not.png",
104+
name=file.name,
98105
)
99106

100107
path = f"/api/0/projects/{event1.project.organization.slug}/{event1.project.slug}/events/{event1.event_id}/attachments/"
@@ -103,7 +110,8 @@ def test_is_screenshot(self):
103110
response = self.client.get(f"{path}?query=is:screenshot")
104111

105112
assert response.status_code == 200, response.content
106-
assert len(response.data) == 1
107-
assert response.data[0]["id"] == str(attachment1.id)
108-
assert response.data[0]["mimetype"] == "image/png"
109-
assert response.data[0]["event_id"] == attachment1.event_id
113+
assert len(response.data) == 2
114+
for attachment in response.data:
115+
assert attachment["event_id"] == event1.event_id
116+
# foo.png will not be included
117+
assert attachment["name"] in ["screenshot.png", "crash_screenshot.png"]

tests/sentry/api/endpoints/test_group_attachments.py

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -66,31 +66,35 @@ def test_filter(self):
6666
assert len(response.data) == 1
6767
assert response.data[0]["id"] == str(attachment2.id)
6868

69-
def test_screenshot_filter(self):
69+
def test_screenshot_across_groups(self):
7070
self.login_as(user=self.user)
7171

72-
attachment1 = self.create_attachment(type="event.attachment", file_name="screenshot.png")
73-
self.create_attachment(type="event.attachment", file_name="screenshot-not.png")
74-
75-
with self.feature("organizations:event-attachments"):
76-
response = self.client.get(self.path(screenshot=True))
77-
78-
assert response.status_code == 200, response.content
79-
assert len(response.data) == 1
80-
assert response.data[0]["id"] == str(attachment1.id)
81-
82-
def test_second_screenshot_filter(self):
83-
self.login_as(user=self.user)
84-
85-
attachment1 = self.create_attachment(type="event.attachment", file_name="screenshot.png")
86-
self.create_attachment(type="event.attachment", file_name="screenshot-not.png")
72+
min_ago = before_now(minutes=1).isoformat()
73+
group1_event = self.store_event(
74+
data={"fingerprint": ["group1"], "timestamp": min_ago}, project_id=self.project.id
75+
)
76+
self.create_attachment(file_name="screenshot.png", event_id=group1_event.event_id)
77+
self.create_attachment(file_name="screenshot-1.png", event_id=group1_event.event_id)
78+
# This will not be included as name doesn't contain 'screenshot'
79+
self.create_attachment(file_name="foo.png", event_id=group1_event.event_id)
80+
group2_event = self.store_event(
81+
data={"fingerprint": ["group2"], "timestamp": min_ago}, project_id=self.project.id
82+
)
83+
self.create_attachment(file_name="crash_screenshot.png", event_id=group2_event.event_id)
8784

8885
with self.feature("organizations:event-attachments"):
8986
response = self.client.get(self.path(screenshot=True))
9087

9188
assert response.status_code == 200, response.content
92-
assert len(response.data) == 1
93-
assert response.data[0]["id"] == str(attachment1.id)
89+
assert len(response.data) == 3
90+
for attachment in response.data:
91+
# foo.png will not be included
92+
assert attachment["name"] in [
93+
"screenshot.png",
94+
"screenshot-1.png",
95+
"crash_screenshot.png",
96+
]
97+
assert attachment["event_id"] in [group1_event.event_id, group2_event.event_id]
9498

9599
def test_without_feature(self):
96100
self.login_as(user=self.user)

0 commit comments

Comments
 (0)