Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,4 @@ jobs:
with:
python-version: "3.14"
- name: Run ${{ matrix.tool }} try repo
run: SKIP=check-jira-reference-in-todo,go-revive,go-fmt,go-imports,check-number-of-lines-count uvx ${{ matrix.tool }} try-repo "$PWD" --all-files --verbose
run: SKIP=check-jira-reference-in-todo,go-revive,go-fmt,go-imports,check-number-of-lines-count,check-ownership uvx ${{ matrix.tool }} try-repo "$PWD" --all-files --verbose
26 changes: 18 additions & 8 deletions dev_tools/check_ownership.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@
from pathlib import Path
from typing import TYPE_CHECKING

from whoowns.ownership_utils import GithubOwnerShip, OwnerShipEntry, check_git, get_ownership_entries
from whoowns.ownership_utils import (
GithubOwnerShip,
OwnerShipEntry,
check_git,
find_codeowners_file,
get_ownership_entries,
)

from dev_tools.git_hook_utils import create_default_parser

Expand All @@ -26,6 +32,7 @@ class ReturnCode(IntFlag):
ERROR_MULTIPLE_FOLDER_OWNERS = auto()
ERROR_RULE_IS_INEFFECTIVE = auto()
ERROR_FILE_WITHOUT_TEAM_OWNERSHIP = auto()
ERROR_NO_CODEOWNERS_FILE = auto()


def check_if_all_codeowners_folders_exist(repo_dir: Path, entries: Iterable[OwnerShipEntry]) -> ReturnCode:
Expand Down Expand Up @@ -135,12 +142,11 @@ def _find_ineffective_rules(
return return_code


def get_codeowners_path(repo_dir: Path) -> Path:
return repo_dir / ".github" / "CODEOWNERS"


def perform_all_codeowners_checks(repo_dir: Path) -> ReturnCode:
codeowners = get_codeowners_path(repo_dir)
codeowners = find_codeowners_file(repo_dir)
if codeowners is None:
print("No CODEOWNERS file found. Skipping ownership checks.")
return ReturnCode.ERROR_NO_CODEOWNERS_FILE
return_code = ReturnCode.SUCCESS
all_entries = list(get_ownership_entries(codeowners))

Expand Down Expand Up @@ -170,10 +176,14 @@ def check_for_files_without_team_ownership(
print("No codeowners-owner provided. Skipping check.")
return ReturnCode.SUCCESS

codeowners = get_codeowners_path(repo_dir)
codeowners = find_codeowners_file(repo_dir)
if codeowners is None:
print("No CODEOWNERS file found. Skipping check.")
return ReturnCode.ERROR_NO_CODEOWNERS_FILE

changed_files = [file.resolve() for file in changed_files]
files_to_check = get_git_tracked_files(repo_dir) if codeowners in changed_files else changed_files
ownership_service = GithubOwnerShip(repo_dir, repo_dir / ".github" / "CODEOWNERS")
ownership_service = GithubOwnerShip(repo_dir, codeowners)
files_owned_by_codeowners_file_owners = [
file for file in files_to_check if file != codeowners and ownership_service.is_owned_by(file, codeowners_owner)
]
Expand Down
13 changes: 1 addition & 12 deletions packages/whoowns/whoowns/find_owner.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import sys
from pathlib import Path

from whoowns.ownership_utils import GithubOwnerShip, check_git
from whoowns.ownership_utils import GithubOwnerShip, check_git, find_codeowners_file


def main() -> int:
Expand Down Expand Up @@ -68,17 +68,6 @@ def get_owners(item: Path, level: int) -> dict[str, tuple[str, ...]]:
return {str(item.relative_to(repo_dir)): ownership.get_owners(item) for item in items}


def find_codeowners_file(repo_dir: Path) -> Path | None:
relative_codeowner_paths = [".github/CODEOWNERS", "CODEOWNERS", "docs/CODEOWNERS"]
for relative_path in relative_codeowner_paths:
codeowners_file = repo_dir / relative_path
if codeowners_file.exists():
return codeowners_file

print(f"Error: No CODEOWNERS file found (candidates: {', '.join(relative_codeowner_paths)}).")
return None


def print_owners(owners: dict[str, tuple[str, ...]]) -> None:
max_path_length = max((len(item) for item in owners), default=0)
for item, owner in owners.items():
Expand Down
11 changes: 11 additions & 0 deletions packages/whoowns/whoowns/ownership_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ def get_codeowners_path(repo_dir: Path) -> Path:
return repo_dir / ".github" / "CODEOWNERS"


def find_codeowners_file(repo_dir: Path) -> Path | None:
relative_codeowner_paths = [".github/CODEOWNERS", "CODEOWNERS", "docs/CODEOWNERS"]
for relative_path in relative_codeowner_paths:
codeowners_file = repo_dir / relative_path
if codeowners_file.exists():
return codeowners_file

print(f"Error: No CODEOWNERS file found (candidates: {', '.join(relative_codeowner_paths)}).")
return None


class OwnerShipEntry:
"""Represent a single entry in a CODEOWNERS file."""

Expand Down