Skip to content

Commit

Permalink
codereview(CI): Fetch all owners and assign them as reviewers as well
Browse files Browse the repository at this point in the history
  • Loading branch information
chouetz committed Jun 20, 2024
1 parent 30d3f4d commit c8be832
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 21 deletions.
4 changes: 2 additions & 2 deletions tasks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
trace_agent,
vscode,
)
from tasks.assign_pr import add_team_labels
from tasks.assign_pr import add_labels_and_reviewers
from tasks.build_tags import audit_tag_impact, print_default_build_tags
from tasks.codecov import apply_missing_coverage, codecov, upload_coverage_to_s3
from tasks.components import lint_components, lint_fxutil_oneshot_test
Expand Down Expand Up @@ -144,7 +144,7 @@
ns.add_task(build_messagetable)
ns.add_task(get_impacted_packages)
ns.add_task(modules.go_work)
ns.add_task(add_team_labels)
ns.add_task(add_labels_and_reviewers)
ns.add_task(get_modified_packages)
ns.add_task(send_unit_tests_stats)
# To deprecate
Expand Down
61 changes: 42 additions & 19 deletions tasks/assign_pr.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,32 @@
import json
import os
import re
from collections import Counter

from invoke import task

from tasks.libs.pipeline_notifications import read_owners
from tasks.libs.owners.parsing import read_owners


class Owner:
def __init__(self, name, github_team, label="team/agent-platform"):
self.name = name
self.github_team = github_team
self.label = label

def __hash__(self) -> int:
return hash(self.name) ^ hash(self.github_team)

def __eq__(self, __value) -> bool:
return isinstance(__value, Owner) and self.name == __value.name and self.github_team == __value.github_team

def __repr__(self) -> str:
return f"Owner(name:{self.name}, github_team:{self.github_team}, label:{self.label})"


@task
def add_team_labels(ctx, pr_id, pr_title=None):
def add_labels_and_reviewers(ctx, pr_id, pr_title=None):
"""
Add team labels to a PR based on the changed dependencies
Add team labels and reviewers to a dependabot bump PR based on the changed dependencies
"""

codeowners = read_owners(".github/CODEOWNERS")
Expand All @@ -21,6 +36,9 @@ def add_team_labels(ctx, pr_id, pr_title=None):
title_words = ctx.run(f"gh pr view {pr_id} | head -n 1", hide=True).stdout.split()[1:]
else:
title_words = pr_title.split()
if title_words[0] != "Bump":
print("This is not a (dependabot) bump PR, this action should not be run on it.")
return
dependency = title_words[1]
if "group" in title_words: # dependabot defines group. Currently dep name is part of the group name
group_index = title_words.index("group")
Expand All @@ -29,7 +47,7 @@ def add_team_labels(ctx, pr_id, pr_title=None):
folder = {title_words[-1][1:]} if title_words[-2] == "in" else "."

# Find the responsible person for each file
owners = []
owners = set()
for root, _, files in os.walk(folder):
if root == "./.git" or any(root.startswith(prefix) for prefix in ["./venv", "./.git/"]):
continue
Expand All @@ -38,32 +56,29 @@ def add_team_labels(ctx, pr_id, pr_title=None):
norm_path = os.path.normpath(file_path)
if "docs/" in file_path.casefold():
continue
with open(file_path, "r") as f:
with open(file_path) as f:
try:
for line in f:
if is_go_module(dependency):
if import_module.match(line):
owners.extend([owner[1] for owner in codeowners.of(norm_path)])
owners.add(get_owner(norm_path, codeowners))
break
elif dependency in line:
owners.extend([owner[1] for owner in codeowners.of(norm_path)])
owners.add(get_owner(norm_path, codeowners))
break
except UnicodeDecodeError:
continue
c = Counter(owners)
responsible = c.most_common(1)[0][0].replace('@Datadog/', '').replace('@DataDog/', '')
# Hardcode for USM as owner name does not match team label name
if responsible == "universal-service-monitoring":
responsible = "usm"

# Retrieve & assign labels
# Retrieve & assign labels and reviewers
team_labels = [team["name"] for team in json.loads(ctx.run("gh label list -S team --json name", hide=True).stdout)]
try:
label = next(label for label in team_labels if responsible in label)
except StopIteration:
label = "team/agent-platform"
for owner in owners:
try:
owner.label = next(label for label in team_labels if owner.name in label)
except StopIteration:
pass # Agent platform is already set by default
ctx.run(f"gh pr edit {pr_id} --remove-label \"team/triage\"")
ctx.run(f"gh pr edit {pr_id} --add-label \"{label}\"")
ctx.run(f"gh pr edit {pr_id} --add-label \"{','.join(owner.label for owner in owners)}\"")
ctx.run(f"gh pr edit {pr_id} --add-reviewer \"{','.join(owner.github_team for owner in owners)}\"")


def is_go_module(module):
Expand Down Expand Up @@ -95,3 +110,11 @@ def is_go_module(module):
"sigs.k8s.io",
]
return any(module.startswith(start) for start in starts)


def get_owner(file_path, codeowners):
github_team = codeowners.of(file_path)[0][1]
team_name = github_team.replace("@Datadog/", "").replace("@DataDog/", "")
if team_name == "universal-service-monitoring":
team_name = "usm"
return Owner(team_name, github_team)

0 comments on commit c8be832

Please sign in to comment.