def test_get_owners_when_codeowners_and_issueowners_exists(self): self.team = self.create_team( organization=self.organization, slug="tiger-team", members=[self.user] ) self.team2 = self.create_team( organization=self.organization, slug="dolphin-team", members=[self.user] ) self.project = self.create_project( organization=self.organization, teams=[self.team, self.team2] ) self.code_mapping = self.create_code_mapping(project=self.project) rule_a = Rule(Matcher("path", "*.py"), [Owner("team", self.team.slug)]) rule_b = Rule(Matcher("path", "src/*"), [Owner("user", self.user.email)]) rule_c = Rule(Matcher("path", "*.py"), [Owner("team", self.team2.slug)]) ProjectOwnership.objects.create( project_id=self.project.id, schema=dump_schema([rule_a, rule_b]), fallthrough=True ) self.create_codeowners( self.project, self.code_mapping, raw="*.py @tiger-team", schema=dump_schema([rule_c]) ) self.assert_ownership_equals( ProjectOwnership.get_owners( self.project.id, {"stacktrace": {"frames": [{"filename": "api/foo.py"}]}} ), ( [ActorTuple(self.team.id, Team), ActorTuple(self.team2.id, Team)], [rule_a, rule_c], ), )
def setUp(self): self.user2 = self.create_user(email="*****@*****.**", is_active=True) self.user3 = self.create_user(email="*****@*****.**", is_active=True) self.team2 = self.create_team(organization=self.organization, members=[self.user, self.user2]) self.project.add_team(self.team2) ProjectOwnership.objects.create( project_id=self.project.id, schema=dump_schema([ grammar.Rule(Matcher("path", "*.py"), [Owner("team", self.team2.slug)]), grammar.Rule(Matcher("path", "*.jsx"), [Owner("user", self.user.email)]), grammar.Rule(Matcher("path", "*.jx"), [Owner("user", self.user3.email)]), grammar.Rule( Matcher("path", "*.cbl"), [ Owner("user", user.email) for user in User.objects.filter( id__in=self.project.member_set.values_list( "user", flat=True)) ], ), grammar.Rule(Matcher("path", "*.lol"), []), ]), fallthrough=True, )
def test_get_autoassign_owners_only_issueowners_exists(self): rule_a = Rule(Matcher("path", "*.py"), [Owner("team", self.team.slug)]) rule_b = Rule(Matcher("path", "src/*"), [Owner("user", self.user.email)]) ProjectOwnership.objects.create( project_id=self.project.id, schema=dump_schema([rule_a, rule_b]), ) # No data matches assert ProjectOwnership.get_autoassign_owners(self.project.id, {}) == (False, [], False) # No autoassignment on match assert ProjectOwnership.get_autoassign_owners( self.project.id, {"stacktrace": { "frames": [{ "filename": "foo.py" }] }}) == (False, [self.team], False) # autoassignment is True owner = ProjectOwnership.objects.get(project_id=self.project.id) owner.auto_assignment = True owner.save() assert ProjectOwnership.get_autoassign_owners( self.project.id, {"stacktrace": { "frames": [{ "filename": "foo.py" }] }}) == (True, [self.team], False)
def setUp(self): self.user = self.create_user(email="*****@*****.**", is_active=True) self.user2 = self.create_user(email="*****@*****.**", is_active=True) self.organization = self.create_organization(owner=self.user) self.team = self.create_team(organization=self.organization) self.project = self.create_project(name="Test", teams=[self.team]) OrganizationMemberTeam.objects.create( organizationmember=OrganizationMember.objects.get( user=self.user, organization=self.organization), team=self.team, ) self.create_member(user=self.user2, organization=self.organization, teams=[self.team]) ProjectOwnership.objects.create( project_id=self.project.id, schema=dump_schema([ grammar.Rule(Matcher("path", "*.py"), [Owner("team", self.team.slug)]), grammar.Rule(Matcher("path", "*.jx"), [Owner("user", self.user2.email)]), grammar.Rule( Matcher("path", "*.cbl"), [ Owner("user", self.user.email), Owner("user", self.user2.email) ], ), ]), fallthrough=True, )
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_notify_users_with_owners(self): user = self.create_user(email="*****@*****.**", is_active=True) user2 = self.create_user(email="*****@*****.**", is_active=True) organization = self.create_organization(owner=user) team = self.create_team(organization=organization) project = self.create_project(name="Test", teams=[team]) OrganizationMemberTeam.objects.create( organizationmember=OrganizationMember.objects.get(user=user, organization=organization), team=team, ) self.create_member(user=user2, organization=organization, teams=[team]) self.group = self.create_group( first_seen=timezone.now(), last_seen=timezone.now(), project=project, message="hello world", logger="root", ) ProjectOwnership.objects.create( project_id=project.id, schema=dump_schema( [ grammar.Rule(Matcher("path", "*.py"), [Owner("team", team.slug)]), grammar.Rule(Matcher("path", "*.jx"), [Owner("user", user2.email)]), grammar.Rule( Matcher("path", "*.cbl"), [Owner("user", user.email), Owner("user", user2.email)], ), ] ), fallthrough=True, ) event_all_users = self.store_event( data=self.make_event_data("foo.cbl"), project_id=project.id ) self.assert_notify(event_all_users, [user.email, user2.email]) event_team = self.store_event(data=self.make_event_data("foo.py"), project_id=project.id) self.assert_notify(event_team, [user.email, user2.email]) event_single_user = self.store_event( data=self.make_event_data("foo.jx"), project_id=project.id ) self.assert_notify(event_single_user, [user2.email]) # Make sure that disabling mail alerts works as expected NotificationSetting.objects.update_settings( ExternalProviders.EMAIL, NotificationSettingTypes.ISSUE_ALERTS, NotificationSettingOptionValues.NEVER, user=user2, project=project, ) event_all_users = self.store_event( data=self.make_event_data("foo.cbl"), project_id=project.id ) self.assert_notify(event_all_users, [user.email])
def test_basic(self): owners = [ Owner("user", self.user.email), Owner("team", self.team.slug) ] assert resolve_actors(owners, self.project.id) == { owners[0]: Actor(self.user.id, User), owners[1]: Actor(self.team.id, Team), }
def test_get_autoassign_owners_when_codeowners_and_issueowners_exists( self): self.team = self.create_team(organization=self.organization, slug="tiger-team", members=[self.user]) self.team2 = self.create_team(organization=self.organization, slug="dolphin-team", members=[self.user]) self.project = self.create_project(organization=self.organization, teams=[self.team, self.team2]) self.code_mapping = self.create_code_mapping(project=self.project) rule_a = Rule(Matcher("path", "*.py"), [Owner("team", self.team.slug)]) rule_b = Rule(Matcher("path", "src/*"), [Owner("user", self.user.email)]) rule_c = Rule(Matcher("path", "*.py"), [Owner("team", self.team2.slug)]) ProjectOwnership.objects.create(project_id=self.project.id, schema=dump_schema([rule_a, rule_b]), fallthrough=True) self.create_codeowners(self.project, self.code_mapping, raw="*.py @tiger-team", schema=dump_schema([rule_c])) # No autoassignment on match assert ProjectOwnership.get_autoassign_owners( self.project.id, {"stacktrace": { "frames": [{ "filename": "api/foo.py" }] }}) == (False, [self.team, self.team2], False) # autoassignment is True owner = ProjectOwnership.objects.get(project_id=self.project.id) owner.auto_assignment = True owner.save() assert ProjectOwnership.get_autoassign_owners( self.project.id, {"stacktrace": { "frames": [{ "filename": "api/foo.py" }] }}) == (True, [self.team, self.team2], False) # # more than 2 matches assert ProjectOwnership.get_autoassign_owners( self.project.id, {"stacktrace": { "frames": [{ "filename": "src/foo.py" }] }}) == (True, [self.user, self.team], False)
def test_parse_rules(): assert parse_rules(fixture_data) == [ Rule(Matcher('path', '*.js'), [Owner('team', 'frontend'), Owner('user', '*****@*****.**')]), Rule(Matcher('url', 'http://google.com/*'), [Owner('team', 'backend')]), Rule(Matcher('path', 'src/sentry/*'), [Owner('user', '*****@*****.**')]), ]
def test_parse_rules(): assert parse_rules(fixture_data) == [ Rule(Matcher("path", "*.js"), [Owner("team", "frontend"), Owner("user", "*****@*****.**")]), Rule(Matcher("url", "http://google.com/*"), [Owner("team", "backend")]), Rule(Matcher("path", "src/sentry/*"), [Owner("user", "*****@*****.**")]), ]
def make_ownership(self): rule_a = Rule(Matcher("path", "src/*"), [Owner("user", self.user.email)]) rule_b = Rule(Matcher("path", "tests/*"), [Owner("team", self.team.name)]) rule_c = Rule(Matcher("path", "src/app/*"), [Owner("team", self.team.name)]) ProjectOwnership.objects.create( project_id=self.project.id, schema=dump_schema([rule_a, rule_b, rule_c]), fallthrough=True, auto_assignment=True, )
def test_get_owners_basic(self): rule_a = Rule(Matcher("path", "*.py"), [Owner("team", self.team.slug)]) rule_b = Rule(Matcher("path", "src/*"), [Owner("user", self.user.email)]) ProjectOwnership.objects.create( project_id=self.project.id, schema=dump_schema([rule_a, rule_b]), fallthrough=True ) # No data matches assert ProjectOwnership.get_owners(self.project.id, {}) == (ProjectOwnership.Everyone, None) # Match only rule_a self.assert_ownership_equals( ProjectOwnership.get_owners( self.project.id, {"stacktrace": {"frames": [{"filename": "foo.py"}]}} ), ([Actor(self.team.id, Team)], [rule_a]), ) # Match only rule_b self.assert_ownership_equals( ProjectOwnership.get_owners( self.project.id, {"stacktrace": {"frames": [{"filename": "src/thing.txt"}]}} ), ([Actor(self.user.id, User)], [rule_b]), ) # Matches both rule_a and rule_b self.assert_ownership_equals( ProjectOwnership.get_owners( self.project.id, {"stacktrace": {"frames": [{"filename": "src/foo.py"}]}} ), ([Actor(self.team.id, Team), Actor(self.user.id, User)], [rule_a, rule_b]), ) assert ProjectOwnership.get_owners( self.project.id, {"stacktrace": {"frames": [{"filename": "xxxx"}]}} ) == (ProjectOwnership.Everyone, None) # When fallthrough = False, we don't implicitly assign to Everyone owner = ProjectOwnership.objects.get(project_id=self.project.id) owner.fallthrough = False owner.save() assert ProjectOwnership.get_owners( self.project.id, {"stacktrace": {"frames": [{"filename": "xxxx"}]}} ) == ([], None) self.assert_ownership_equals( ProjectOwnership.get_owners( self.project.id, {"stacktrace": {"frames": [{"filename": "src/foo.py"}]}} ), ([Actor(self.team.id, Team), Actor(self.user.id, User)], [rule_a, rule_b]), )
def make_ownership(self, extra_rules=None): rules = [ Rule(Matcher("path", "src/*"), [Owner("user", self.user.email)]), Rule(Matcher("path", "tests/*"), [Owner("team", self.team.name)]), Rule(Matcher("path", "src/app/*"), [Owner("team", self.team.name)]), ] if extra_rules: rules.extend(extra_rules) ProjectOwnership.objects.create( project_id=self.project.id, schema=dump_schema(rules), fallthrough=True, auto_assignment=True, )
def test_owner_assignment_extra_groups(self): extra_user = self.create_user() self.create_team_membership(self.team, user=extra_user) self.make_ownership( [Rule(Matcher("path", "src/app/things/in/*"), [Owner("user", extra_user.email)])], ) event = self.store_event( data={ "message": "oh no", "platform": "python", "stacktrace": {"frames": [{"filename": "src/app/things/in/a/path/example2.py"}]}, }, project_id=self.project.id, ) cache_key = write_event_to_cache(event) post_process_group( is_new=False, is_regression=False, is_new_group_environment=False, cache_key=cache_key, group_id=event.group_id, ) assignee = event.group.assignee_set.first() assert assignee.user == extra_user assert assignee.team is None owners = list(GroupOwner.objects.filter(group=event.group)) assert len(owners) == 2 assert set([(extra_user.id, None), (None, self.team.id)]) == { (o.user_id, o.team_id) for o in owners }
def test_get_owners_when_codeowners_exists_and_no_issueowners(self): # This case will never exist bc we create a ProjectOwnership record if none exists when creating a ProjectCodeOwner record. # We have this testcase for potential corrupt data. self.team = self.create_team(organization=self.organization, slug="tiger-team", members=[self.user]) self.code_mapping = self.create_code_mapping(project=self.project) rule_a = Rule(Matcher("path", "*.js"), [Owner("team", self.team.slug)]) self.create_codeowners( self.project, self.code_mapping, raw="*.js @tiger-team", schema=dump_schema([rule_a]), ) self.assert_ownership_equals( ProjectOwnership.get_owners( self.project.id, {"stacktrace": { "frames": [{ "filename": "src/foo.js" }] }}), ( [ActorTuple(self.team.id, Team)], [rule_a], ), )
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"] == six.text_type(self.user.id) assert resp.data["rule"] == Matcher("path", "*.py") assert len(resp.data["rules"]) == 1
def test_matching_non_existing_owner(self): rule_a = Rule(Matcher("path", "*"), [Owner("user", "*****@*****.**")]) 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_get_autoassign_owners_only_codeowners_exists(self): # This case will never exist bc we create a ProjectOwnership record if none exists when creating a ProjectCodeOwner record. # We have this testcase for potential corrupt data. self.team = self.create_team(organization=self.organization, slug="tiger-team", members=[self.user]) self.code_mapping = self.create_code_mapping(project=self.project) rule_a = Rule(Matcher("path", "*.js"), [Owner("team", self.team.slug)]) self.create_codeowners( self.project, self.code_mapping, raw="*.js @tiger-team", schema=dump_schema([rule_a]), ) # No data matches assert ProjectOwnership.get_autoassign_owners(self.project.id, {}) == (False, [], False) # No autoassignment on match assert ProjectOwnership.get_autoassign_owners( self.project.id, {"stacktrace": { "frames": [{ "filename": "foo.js" }] }}) == (False, [self.team], True)
def test_get_owners_basic(self): matcher = Matcher('path', '*.py') ProjectOwnership.objects.create( project_id=self.project.id, schema=dump_schema([ Rule(matcher, [ Owner('user', self.user.email), Owner('team', self.team.slug), ]), ]), fallthrough=True, ) # No data matches assert ProjectOwnership.get_owners(self.project.id, {}) == (ProjectOwnership.Everyone, None) assert ProjectOwnership.get_owners(self.project.id, { 'sentry.interfaces.Stacktrace': { 'frames': [{ 'filename': 'foo.py', }] } }) == ([Actor(self.user.id, User), Actor(self.team.id, Team)], matcher) assert ProjectOwnership.get_owners(self.project.id, { 'sentry.interfaces.Stacktrace': { 'frames': [{ 'filename': 'xxxx', }] } }) == (ProjectOwnership.Everyone, None) # When fallthrough = False, we don't implicitly assign to Everyone ProjectOwnership.objects.filter( project_id=self.project.id, ).update(fallthrough=False) assert ProjectOwnership.get_owners(self.project.id, { 'sentry.interfaces.Stacktrace': { 'frames': [{ 'filename': 'xxxx', }] } }) == ([], None)
def make_ownership(self): rule_a = Rule(Matcher('path', 'src/*'), [ Owner('user', self.user.email), ]) rule_b = Rule(Matcher('path', 'tests/*'), [ Owner('team', self.team.name), ]) rule_c = Rule(Matcher('path', 'src/app/*'), [ Owner('team', self.team.name), ]) ProjectOwnership.objects.create( project_id=self.project.id, schema=dump_schema([rule_a, rule_b, rule_c]), fallthrough=True, auto_assignment=True, )
def setUp(self): self.user2 = self.create_user(email="*****@*****.**", is_active=True) self.create_member(user=self.user2, organization=self.organization, teams=[self.team]) ProjectOwnership.objects.create( project_id=self.project.id, schema=dump_schema( [ grammar.Rule(Matcher("path", "*.py"), [Owner("team", self.team.slug)]), grammar.Rule(Matcher("path", "*.jx"), [Owner("user", self.user2.email)]), grammar.Rule( Matcher("path", "*.cbl"), [Owner("user", self.user.email), Owner("user", self.user2.email)], ), ] ), fallthrough=True, )
def test_parse_rules(): assert parse_rules(fixture_data) == [ Rule(Matcher("path", "*.js"), [Owner("team", "frontend"), Owner("user", "*****@*****.**")]), Rule(Matcher("url", "http://google.com/*"), [Owner("team", "backend")]), Rule(Matcher("path", "src/sentry/*"), [Owner("user", "*****@*****.**")]), Rule(Matcher("tags.foo", "bar"), [Owner("user", "*****@*****.**")]), Rule(Matcher("tags.foo", "bar baz"), [Owner("user", "*****@*****.**")]), Rule(Matcher("module", "foo.bar"), [Owner("team", "workflow")]), Rule(Matcher("module", "foo bar"), [Owner("user", "*****@*****.**")]), ]
def test_owner_assignment_when_owners_have_been_unassigned(self): """ Test that ensures that if certain assignees get unassigned, and project rules are changed then the new group assignees should be re-calculated and re-assigned """ # Create rules and check assignees self.make_ownership() event = self.store_event( data={ "message": "oh no", "platform": "python", "stacktrace": { "frames": [{ "filename": "src/app/example.py" }] }, }, project_id=self.project.id, ) cache_key = write_event_to_cache(event) post_process_group( is_new=False, is_regression=False, is_new_group_environment=False, cache_key=cache_key, group_id=event.group_id, ) assignee = event.group.assignee_set.first() assert assignee.user == self.user user_3 = self.create_user() self.create_team_membership(self.team, user=user_3) # De-assign group assignees GroupAssignee.objects.deassign(event.group, self.user) assert event.group.assignee_set.first() is None # Change ProjectOwnership rules rules = [ Rule(Matcher("path", "src/*"), [Owner("user", user_3.email)]), ] self.prj_ownership.schema = dump_schema(rules) self.prj_ownership.save() cache_key = write_event_to_cache(event) post_process_group( is_new=False, is_regression=False, is_new_group_environment=False, cache_key=cache_key, group_id=event.group_id, ) # Group should be re-assigned to the new group owner assignee = event.group.assignee_set.first() assert assignee.user == user_3
def setUp(self): self.user_1 = self.create_user(email="*****@*****.**") self.user_2 = self.create_user(email="*****@*****.**") self.user_3 = self.create_user(email="*****@*****.**") self.organization = self.create_organization(name="Padishah Emperor") self.team_1 = self.create_team( organization=self.organization, name="House Atreides", members=[self.user_1, self.user_2], ) self.team_2 = self.create_team( organization=self.organization, name="Bene Gesserit", members=[self.user_1, self.user_3] ) self.project = self.create_project( name="Settle Arrakis", organization=self.organization, teams=[self.team_1, self.team_2] ) self.rule_1 = Rule(Matcher("path", "*.js"), [Owner("team", self.team_1.slug)]) self.rule_2 = Rule(Matcher("path", "*.js"), [Owner("team", self.team_2.slug)]) self.rule_3 = Rule(Matcher("path", "*.js"), [Owner("user", self.user_1.email)])
def test_dump_schema(): assert dump_schema([Rule(Matcher("path", "*.js"), [Owner("team", "frontend")])]) == { "$version": 1, "rules": [ { "matcher": {"type": "path", "pattern": "*.js"}, "owners": [{"type": "team", "identifier": "frontend"}], } ], }
def test_teams(self): # Normal team owner1 = Owner('team', self.team.slug) actor1 = Actor(self.team.id, Team) # Team that doesn't exist owner2 = Owner('team', 'nope') actor2 = None # A team that's not ours otherteam = Team.objects.exclude(projectteam__project_id=self.project.id)[0] owner3 = Owner('team', otherteam.slug) actor3 = None assert resolve_actors([owner1, owner2, owner3], self.project.id) == { owner1: actor1, owner2: actor2, owner3: actor3, }
def setUp(self): from sentry.ownership.grammar import Rule self.user = self.create_user(email='*****@*****.**', is_active=True) self.user2 = self.create_user(email='*****@*****.**', is_active=True) self.organization = self.create_organization(owner=self.user) self.team = self.create_team(organization=self.organization) self.project = self.create_project(name='Test', teams=[self.team]) OrganizationMemberTeam.objects.create( organizationmember=OrganizationMember.objects.get( user=self.user, organization=self.organization, ), team=self.team, ) self.create_member(user=self.user2, organization=self.organization, teams=[self.team]) self.group = self.create_group( first_seen=timezone.now(), last_seen=timezone.now(), project=self.project, message='hello world', logger='root', ) ProjectOwnership.objects.create( project_id=self.project.id, schema=dump_schema([ Rule(Matcher('path', '*.py'), [ Owner('team', self.team.slug), ]), Rule(Matcher('path', '*.jx'), [ Owner('user', self.user2.email), ]), Rule(Matcher('path', '*.cbl'), [ Owner('user', self.user.email), Owner('user', self.user2.email), ]) ]), fallthrough=True, )
def setUp(self): from sentry.ownership.grammar import Rule self.user = self.create_user(email="*****@*****.**", is_active=True) self.user2 = self.create_user(email="*****@*****.**", is_active=True) self.organization = self.create_organization(owner=self.user) self.team = self.create_team(organization=self.organization) self.project = self.create_project(name="Test", teams=[self.team]) OrganizationMemberTeam.objects.create( organizationmember=OrganizationMember.objects.get( user=self.user, organization=self.organization), team=self.team, ) self.create_member(user=self.user2, organization=self.organization, teams=[self.team]) self.group = self.create_group( first_seen=timezone.now(), last_seen=timezone.now(), project=self.project, message="hello world", logger="root", ) ProjectOwnership.objects.create( project_id=self.project.id, schema=dump_schema([ Rule(Matcher("path", "*.py"), [Owner("team", self.team.slug)]), Rule(Matcher("path", "*.jx"), [Owner("user", self.user2.email)]), Rule( Matcher("path", "*.cbl"), [ Owner("user", self.user.email), Owner("user", self.user2.email) ], ), ]), fallthrough=True, )
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
def test_abs_path_when_filename_present(self): frame = { "filename": "computer.cpp", "abs_path": "C:\\My\\Path\\computer.cpp", } rule = Rule(Matcher("path", "*My\\Path*"), [Owner("team", self.team.slug)]) ProjectOwnership.objects.create(project_id=self.project.id, schema=dump_schema([rule]), fallthrough=True) assert ProjectOwnership.get_owners( self.project.id, {"stacktrace": { "frames": [frame] }}) == ([ActorTuple(self.team.id, Team)], [rule])