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_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 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 handle_owner_assignment(project, group, event): from sentry.models import GroupAssignee, ProjectOwnership with metrics.timer("post_process.handle_owner_assignment"): # Is the issue already assigned to a team or user? key = "assignee_exists:1:%s" % group.id owners_exists = cache.get(key) if owners_exists is None: owners_exists = group.assignee_set.exists() or group.groupowner_set.exists() # Cache for an hour if it's assigned. We don't need to move that fast. cache.set(key, owners_exists, 3600 if owners_exists else 60) if owners_exists: return auto_assignment, owners, assigned_by_codeowners = ProjectOwnership.get_autoassign_owners( group.project_id, event.data ) if auto_assignment and owners: GroupAssignee.objects.assign(group, owners[0]) if assigned_by_codeowners: analytics.record( "codeowners.assignment", organization_id=project.organization_id, project_id=project.id, group_id=group.id, ) if owners: try: handle_group_owners(project, group, owners) except Exception: logger.exception("Failed to store group owners")
def handle_owner_assignment(project, group, event): from sentry.models import GroupAssignee, ProjectOwnership with metrics.timer("post_process.handle_owner_assignment"): owners_ingestion = features.has("projects:workflow-owners-ingestion", event.project) # Is the issue already assigned to a team or user? key = "assignee_exists:1:%s" % group.id owners_exists = cache.get(key) if owners_exists is None: owners_exists = group.assignee_set.exists() and ( not owners_ingestion or group.groupowner_set.exists()) # Cache for an hour if it's assigned. We don't need to move that fast. cache.set(key, owners_exists, 3600 if owners_exists else 60) if owners_exists: return auto_assignment, owners = ProjectOwnership.get_autoassign_owners( group.project_id, event.data) if auto_assignment and owners: GroupAssignee.objects.assign(group, owners[0]) if owners and owners_ingestion: try: handle_group_owners(project, group, owners) except Exception: logger.exception("Failed to store group owners")
def test_get_autoassign_owners_no_codeowners_or_issueowners(self): assert ProjectOwnership.get_autoassign_owners(self.project.id, {}) == (False, [], False)
def handle_owner_assignment(project, group, event): from sentry.models import GroupAssignee, ProjectOwnership with metrics.timer("post_process.handle_owner_assignment"): with sentry_sdk.start_span( op="post_process.handle_owner_assignment.cache_set_owner"): owner_key = "owner_exists:1:%s" % group.id owners_exists = cache.get(owner_key) if owners_exists is None: owners_exists = group.groupowner_set.exists() # Cache for an hour if it's assigned. We don't need to move that fast. cache.set(owner_key, owners_exists, 3600 if owners_exists else 60) with sentry_sdk.start_span( op="post_process.handle_owner_assignment.cache_set_assignee"): # Is the issue already assigned to a team or user? assignee_key = "assignee_exists:1:%s" % group.id assignees_exists = cache.get(assignee_key) if assignees_exists is None: assignees_exists = group.assignee_set.exists() # Cache for an hour if it's assigned. We don't need to move that fast. cache.set(assignee_key, assignees_exists, 3600 if assignees_exists else 60) if owners_exists and assignees_exists: return with sentry_sdk.start_span( op="post_process.handle_owner_assignment.get_autoassign_owners" ): if killswitch_matches_context( "post_process.get-autoassign-owners", { "project_id": project.id, }, ): # see ProjectOwnership.get_autoassign_owners auto_assignment = False owners = [] assigned_by_codeowners = False else: ( auto_assignment, owners, assigned_by_codeowners, ) = ProjectOwnership.get_autoassign_owners( group.project_id, event.data) with sentry_sdk.start_span( op="post_process.handle_owner_assignment.analytics_record"): if auto_assignment and owners and not assignees_exists: assignment = GroupAssignee.objects.assign(group, owners[0], create_only=True) if assignment["new_assignment"] or assignment[ "updated_assignment"]: analytics.record( "codeowners.assignment" if assigned_by_codeowners else "issueowners.assignment", organization_id=project.organization_id, project_id=project.id, group_id=group.id, ) with sentry_sdk.start_span( op="post_process.handle_owner_assignment.handle_group_owners"): if owners and not owners_exists: try: handle_group_owners(project, group, owners) except Exception: logger.exception("Failed to store group owners")