summaryrefslogtreecommitdiffstats
path: root/.github/scripts/analytics
diff options
context:
space:
mode:
authorKirill Rysin <[email protected]>2026-04-09 22:09:24 +0200
committerGitHub <[email protected]>2026-04-09 23:09:24 +0300
commitdd7241688046d7fc656d2f4fc85ff0fe438c7869 (patch)
tree529d5481a2807d1341131ea6a419d0030e1811d5 /.github/scripts/analytics
parent739783c2537658fdc0ea29c86369d10d508b9629 (diff)
Mute: TESTOWNERS normalization (#37801)
Diffstat (limited to '.github/scripts/analytics')
-rw-r--r--.github/scripts/analytics/testowners_utils.py34
-rwxr-xr-x.github/scripts/analytics/tests_monitor.py6
2 files changed, 33 insertions, 7 deletions
diff --git a/.github/scripts/analytics/testowners_utils.py b/.github/scripts/analytics/testowners_utils.py
index ed14ef5364e..12b28f39b73 100644
--- a/.github/scripts/analytics/testowners_utils.py
+++ b/.github/scripts/analytics/testowners_utils.py
@@ -1,13 +1,37 @@
-"""TESTOWNERS resolution for analytics (test_results / testowners uploads)."""
+"""TESTOWNERS resolution for analytics (test_results / testowners uploads).
-import os
+``codeowners`` returns ``TEAM:@ydb-platform/<Slug>`` with whatever casing is in
+``.github/TESTOWNERS``. We normalize team slugs to lowercase **here** (on read) so YDB
+``owners`` / downstream marts always contain lowercase slugs without touching the file.
+
+For routing (digest queue, Telegram, GitHub project owner) use :func:`canonical_team_slug`
+from ``github_issue_utils`` — it maps None / empty / unknown to the sentinel ``"unknown"``.
+"""
-from codeowners import CodeOwners
+import os
_MODULE_DIR = os.path.dirname(os.path.abspath(__file__))
_REPO_ROOT = os.path.normpath(os.path.join(_MODULE_DIR, '..', '..', '..'))
TESTOWNERS_FILE = os.path.join(_REPO_ROOT, '.github', 'TESTOWNERS')
+_GITHUB_TEAM_PREFIX = "TEAM:@ydb-platform/"
+
+
+def normalize_github_team_owners_string(owners_str: str) -> str:
+ """Lowercase path after ``TEAM:@ydb-platform/`` in each ``;;``-separated owner token."""
+ if not owners_str or _GITHUB_TEAM_PREFIX not in owners_str:
+ return owners_str
+ parts = owners_str.split(";;")
+ normalized = []
+ for raw in parts:
+ s = raw.strip()
+ if s.startswith(_GITHUB_TEAM_PREFIX):
+ rest = s[len(_GITHUB_TEAM_PREFIX) :]
+ normalized.append(_GITHUB_TEAM_PREFIX + rest.lower())
+ else:
+ normalized.append(s)
+ return ";;".join(normalized)
+
def sort_codeowners_lines(codeowners_lines):
def path_specificity(line):
@@ -44,6 +68,8 @@ def get_testowners_for_tests(tests_data):
Entry may be a dict with key ``suite_folder`` (upload pipeline) or any object with
``classname`` (e.g. generate-summary.TestResult — same path as suite_folder in JSON).
"""
+ from codeowners import CodeOwners
+
with open(TESTOWNERS_FILE, 'r') as file:
data = file.readlines()
owners_obj = CodeOwners(''.join(sort_codeowners_lines(data)))
@@ -51,5 +77,5 @@ def get_testowners_for_tests(tests_data):
target_path = _suite_path_for_codeowners(test)
owners = owners_obj.of(target_path)
owners_str = ';;'.join([':'.join(x) for x in owners])
- _set_owners_field(test, owners_str)
+ _set_owners_field(test, normalize_github_team_owners_string(owners_str))
return tests_data
diff --git a/.github/scripts/analytics/tests_monitor.py b/.github/scripts/analytics/tests_monitor.py
index 960134fc840..cd9ef025099 100755
--- a/.github/scripts/analytics/tests_monitor.py
+++ b/.github/scripts/analytics/tests_monitor.py
@@ -16,6 +16,7 @@ from github_issue_utils import (
compute_effective_analytics_row,
min_area_by_owner_team_from_rows,
)
+from testowners_utils import normalize_github_team_owners_string
def create_tables(ydb_wrapper, table_path):
@@ -281,14 +282,13 @@ def _annotate_effective_owner_change_columns(df, last_exist_df):
immediate = curr
-
def compute_owner(owner):
if not owner or owner == '':
- return 'Unknown'
+ return 'unknown'
elif ';;' in owner:
parts = owner.split(';;', 1)
if 'TEAM' in parts[0]:
- return parts[0]
+ return normalize_github_team_owners_string(parts[0])
else:
return parts[1]
else: