Files
2024-02-15 17:01:50 +00:00

232 lines
8.5 KiB
Python

from django.urls import reverse
from sentry.models.projectownership import ProjectOwnership
from sentry.ownership.grammar import Matcher, Owner, Rule, dump_schema
from sentry.testutils.cases import APITestCase
from sentry.testutils.silo import region_silo_test
from sentry.testutils.skips import requires_kafka, requires_snuba
pytestmark = [requires_snuba, requires_kafka]
@region_silo_test
class ProjectOwnershipEndpointTestCase(APITestCase):
def setUp(self):
self.login_as(user=self.user)
self.user2 = self.create_user("[email protected]")
self.user3 = self.create_user("[email protected]")
self.team = self.create_team(
organization=self.organization, slug="tiger-team", members=[self.user]
)
self.team2 = self.create_team(
organization=self.organization, slug="tiger-team2", members=[self.user2]
)
self.team3 = self.create_team(
organization=self.organization, slug="tiger-team3", members=[self.user3]
)
self.project = self.create_project(
organization=self.organization, teams=[self.team, self.team2, self.team3], slug="bengal"
)
def test_no_rules(self):
event1 = self.store_event(
data={"stacktrace": {"frames": [{"filename": "foo.py"}]}}, project_id=self.project.id
)
self.path = reverse(
"sentry-api-0-event-owners",
kwargs={
"organization_slug": self.organization.slug,
"project_slug": self.project.slug,
"event_id": event1.event_id,
},
)
resp = self.client.get(self.path)
assert resp.status_code == 200
assert len(resp.data["owners"]) == 0
assert resp.data["rule"] is None
assert len(resp.data["rules"]) == 0
def test_no_matching_owners(self):
rule_a = Rule(Matcher("path", "bar.py"), [Owner("user", self.user.email)])
ProjectOwnership.objects.create(
project_id=self.project.id, schema=dump_schema([rule_a]), fallthrough=True
)
event1 = self.store_event(
data={"stacktrace": {"frames": [{"filename": "foo.py"}]}}, project_id=self.project.id
)
self.path = reverse(
"sentry-api-0-event-owners",
kwargs={
"organization_slug": self.organization.slug,
"project_slug": self.project.slug,
"event_id": event1.event_id,
},
)
resp = self.client.get(self.path)
assert resp.status_code == 200
assert len(resp.data["owners"]) == 0
assert resp.data["rule"] is None
assert len(resp.data["rules"]) == 0
def test_matching_non_existing_owner(self):
rule_a = Rule(Matcher("path", "*"), [Owner("user", "[email protected]")])
ProjectOwnership.objects.create(
project_id=self.project.id, schema=dump_schema([rule_a]), fallthrough=True
)
event1 = self.store_event(
data={"stacktrace": {"frames": [{"filename": "foo.py"}]}}, project_id=self.project.id
)
self.path = reverse(
"sentry-api-0-event-owners",
kwargs={
"organization_slug": self.organization.slug,
"project_slug": self.project.slug,
"event_id": event1.event_id,
},
)
resp = self.client.get(self.path)
assert resp.status_code == 200
assert len(resp.data["owners"]) == 0
assert resp.data["rule"] == Matcher(type="path", pattern="*")
assert len(resp.data["rules"]) == 1
def test_one_owner(self):
rule_a = Rule(Matcher("path", "*.py"), [Owner("user", self.user.email)])
ProjectOwnership.objects.create(
project_id=self.project.id, schema=dump_schema([rule_a]), fallthrough=True
)
event1 = self.store_event(
data={"stacktrace": {"frames": [{"filename": "foo.py"}]}}, project_id=self.project.id
)
self.path = reverse(
"sentry-api-0-event-owners",
kwargs={
"organization_slug": self.organization.slug,
"project_slug": self.project.slug,
"event_id": event1.event_id,
},
)
resp = self.client.get(self.path)
assert resp.status_code == 200
assert len(resp.data["owners"]) == 1
assert resp.data["owners"][0]["id"] == str(self.user.id)
assert resp.data["rule"] == Matcher("path", "*.py")
assert len(resp.data["rules"]) == 1
def test_multiple_owners(self):
users = [self.user, self.user2, self.user3]
rules = [
Rule(Matcher("path", "*.py"), [Owner("user", users[0].email)]),
Rule(Matcher("path", "*foo*"), [Owner("user", users[1].email)]),
Rule(Matcher("path", "*"), [Owner("user", users[2].email)]),
]
ProjectOwnership.objects.create(
project_id=self.project.id, schema=dump_schema(rules), fallthrough=True
)
event1 = self.store_event(
data={"stacktrace": {"frames": [{"filename": "foo.py"}]}}, project_id=self.project.id
)
self.path = reverse(
"sentry-api-0-event-owners",
kwargs={
"organization_slug": self.organization.slug,
"project_slug": self.project.slug,
"event_id": event1.event_id,
},
)
resp = self.client.get(self.path)
assert resp.status_code == 200
assert len(resp.data["owners"]) == 3
assert [o["id"] for o in resp.data["owners"]] == [str(u.id) for u in users]
assert resp.data["rule"] == Matcher("path", "*.py")
assert len(resp.data["rules"]) == 3
def test_multiple_owners_order_matters(self):
users = [self.user, self.user2, self.user3]
rules = [
Rule(Matcher("path", "*.py"), [Owner("user", users[0].email)]),
Rule(Matcher("path", "*foo*"), [Owner("user", users[1].email)]),
Rule(Matcher("path", "*"), [Owner("user", users[2].email)]),
]
rules.reverse()
ProjectOwnership.objects.create(
project_id=self.project.id, schema=dump_schema(rules), fallthrough=True
)
event1 = self.store_event(
data={"stacktrace": {"frames": [{"filename": "foo.py"}]}}, project_id=self.project.id
)
self.path = reverse(
"sentry-api-0-event-owners",
kwargs={
"organization_slug": self.organization.slug,
"project_slug": self.project.slug,
"event_id": event1.event_id,
},
)
resp = self.client.get(self.path)
assert resp.status_code == 200
assert len(resp.data["owners"]) == 3
assert [o["id"] for o in resp.data["owners"]] == [str(u.id) for u in reversed(users)]
assert resp.data["rule"] == Matcher("path", "*")
assert len(resp.data["rules"]) == 3
def test_owners_of_different_types_ordered_correctly(self):
owners = [self.user, self.team3, self.user2, self.team2, self.user3, self.team]
rules = [
Rule(Matcher("path", "*.py"), [Owner("user", owners[0].email)]),
Rule(Matcher("path", "*py"), [Owner("team", owners[1].slug)]),
Rule(Matcher("path", "*foo*"), [Owner("user", owners[2].email)]),
Rule(Matcher("path", "*y"), [Owner("team", owners[3].slug)]),
Rule(Matcher("path", "*"), [Owner("user", owners[4].email)]),
Rule(Matcher("path", "*o.py"), [Owner("team", owners[5].slug)]),
]
ProjectOwnership.objects.create(
project_id=self.project.id, schema=dump_schema(rules), fallthrough=True
)
event1 = self.store_event(
data={"stacktrace": {"frames": [{"filename": "foo.py"}]}}, project_id=self.project.id
)
self.path = reverse(
"sentry-api-0-event-owners",
kwargs={
"organization_slug": self.organization.slug,
"project_slug": self.project.slug,
"event_id": event1.event_id,
},
)
resp = self.client.get(self.path)
assert resp.status_code == 200
assert len(resp.data["owners"]) == 6
assert [o["id"] for o in resp.data["owners"]] == [str(o.id) for o in owners]
assert [o["type"] for o in resp.data["owners"]] == ["user", "team"] * 3
assert resp.data["rule"] == Matcher("path", "*.py")
assert len(resp.data["rules"]) == 6