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
40 changes: 20 additions & 20 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[tool.coverage.run]
omit = [ "tests/*" ]
omit = ["tests/*"]

[tool.coverage.report]
fail_under = 0
fail_under = 30
skip_empty = true

[tool.coverage.html]
Expand All @@ -14,8 +14,8 @@ line-length = 120
fix = true
output-format = "grouped"

[tool.ruff.format]
exclude = [ ".git", ".venv", ".mypy_cache", ".tox", "__pycache__" ]
[tool.ruff.format]
exclude = [".git", ".venv", ".mypy_cache", ".tox", "__pycache__"]

[tool.mypy]
check_untyped_defs = true
Expand All @@ -27,10 +27,10 @@ show_error_codes = true
warn_unused_ignores = true

[tool.hatch.build.targets.wheel]
packages = [ "webhook_server_container" ]
packages = ["webhook_server_container"]

[tool.uv]
dev-dependencies = [ "ipdb>=0.13.13", "ipython>=8.12.3" ]
dev-dependencies = ["ipdb>=0.13.13", "ipython>=8.12.3"]

[project]
name = "github-webhook-server"
Expand All @@ -41,7 +41,7 @@ readme = "README.md"
license = "Apache-2.0"
classifiers = [
"Programming Language :: Python :: 3",
"Operating System :: OS Independent"
"Operating System :: OS Independent",
]
dependencies = [
"build>=1.2.2.post1",
Expand All @@ -62,23 +62,23 @@ dependencies = [
"string-color>=1.2.3",
"timeout-sampler>=0.0.46",
"uvicorn>=0.31.0",
"uwsgi>=2.0.27"
"uwsgi>=2.0.27",
]

[[project.authors]]
name = "Meni Yakove"
email = " myakove@gmail.com"
[[project.authors]]
name = "Meni Yakove"
email = " myakove@gmail.com"

[[project.authors]]
name = "Ruth Netser"
email = "ruth.netser@gmail.com"
[[project.authors]]
name = "Ruth Netser"
email = "ruth.netser@gmail.com"

[project.urls]
homepage = "https://github.com/myakove/github-webhook-server"
repository = "https://github.com/myakove/github-webhook-server"
Download = "https://quay.io/repository/myakove/github-webhook-server"
"Bug Tracker" = "https://github.com/myakove/github-webhook-server/issues"
[project.urls]
homepage = "https://github.com/myakove/github-webhook-server"
repository = "https://github.com/myakove/github-webhook-server"
Download = "https://quay.io/repository/myakove/github-webhook-server"
"Bug Tracker" = "https://github.com/myakove/github-webhook-server/issues"

[build-system]
requires = [ "hatchling" ]
requires = ["hatchling"]
build-backend = "hatchling.build"
3 changes: 2 additions & 1 deletion pytest.ini
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[pytest]
addopts =
--cov-config=pyproject.toml --cov-report=html --cov-report=term --cov=github_webhook_server
--pdbcls=IPython.terminal.debugger:TerminalPdb
--cov-config=pyproject.toml --cov-report=html --cov-report=term --cov=webhook_server_container
25 changes: 17 additions & 8 deletions webhook_server_container/libs/github_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2057,25 +2057,34 @@ def owners_data_for_changed_files(self) -> dict[str, dict[str, Any]]:

changed_folders = {Path(cf).parent for cf in self.changed_files}

changed_folder_match: list[str] = []
changed_folder_match: list[Path] = []

require_root_approvers: bool = False
require_root_approvers: bool | None = None

for owners_dir, owners_data in self.all_approvers_and_reviewers.items():
if owners_dir == ".":
continue

_owners_dir = Path(owners_dir)

for changed_folder in changed_folders:
if _owners_dir == changed_folder or _owners_dir.parents == changed_folders:
if changed_folder == _owners_dir or _owners_dir in changed_folder.parents:
data[owners_dir] = owners_data
changed_folder_match.append(owners_dir)
if not require_root_approvers:
changed_folder_match.append(_owners_dir)
if require_root_approvers is None:
require_root_approvers = owners_data.get("root-approvers", True)

if [_folder for _folder in changed_folders if str(_folder) not in changed_folder_match]:
if require_root_approvers or require_root_approvers is None:
data["."] = self.all_approvers_and_reviewers.get(".", {})

if require_root_approvers:
data["."] = self.all_approvers_and_reviewers.get(".", {})
else:
for _folder in changed_folders:
for _changed_path in changed_folder_match:
if _folder == _changed_path or _changed_path in _folder.parents:
continue
else:
data["."] = self.all_approvers_and_reviewers.get(".", {})
break

return data

Expand Down
114 changes: 114 additions & 0 deletions webhook_server_container/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import pytest
from starlette.datastructures import Headers

from simple_logger.logger import logging
import yaml
from webhook_server_container.libs.github_api import ProcessGithubWehook
import os

ALL_CHANGED_FILES = [
"OWNERS",
"folder1/OWNERS",
"code/file.py",
"README.md",
"folder2/lib.py",
"folder/folder4/another_file.txt",
"folder5/file",
]


class Tree:
def __init__(self, path: str):
self.type = "blob"
self.path = path

@property
def tree(self):
trees = []
for _path in [
"OWNERS",
"folder1/OWNERS",
"folder2/OWNERS",
"folder/folder4/OWNERS",
"folder5/OWNERS",
]:
trees.append(Tree(_path))
return trees


class ContentFile:
def __init__(self, content: str):
self.content = content

@property
def decoded_content(self):
return self.content


class Repository:
def __init__(self):
self.name = "test-repo"

def get_git_tree(self, sha: str, recursive: bool):
return Tree("")

def get_contents(self, path: str):
owners_data = yaml.dump({
"approvers": ["root_approver1", "root_approver2"],
"reviewers": ["root_reviewer1", "root_reviewer2"],
})

folder1_owners_data = yaml.dump({
"approvers": ["folder1_approver1", "folder1_approver2"],
"reviewers": ["folder1_reviewer1", "folder1_reviewer2"],
})

folder4_owners_data = yaml.dump({
"approvers": ["folder4_approver1", "folder4_approver2"],
"reviewers": ["folder4_reviewer1", "folder4_reviewer2"],
})

folder5_owners_data = yaml.dump({
"root-approvers": False,
"approvers": ["folder5_approver1", "folder5_approver2"],
"reviewers": ["folder5_reviewer1", "folder5_reviewer2"],
})
if path == "OWNERS":
return ContentFile(owners_data)

elif path == "folder1/OWNERS":
return ContentFile(folder1_owners_data)

elif path == "folder2/OWNERS":
return ContentFile(yaml.dump({}))

elif path == "folder/folder4/OWNERS":
return ContentFile(folder4_owners_data)

elif path == "folder":
return ContentFile(yaml.dump({}))

elif path == "folder5/OWNERS":
return ContentFile(folder5_owners_data)


@pytest.fixture(scope="function")
def process_github_webhook(mocker, request):
base_import_path = "webhook_server_container.libs.github_api"
os.environ["WEBHOOK_SERVER_DATA_DIR"] = "webhook_server_container/tests/manifests"

mocker.patch(f"{base_import_path}.get_repository_github_app_api", return_value=True)
mocker.patch("github.AuthenticatedUser", return_value=True)
mocker.patch(f"{base_import_path}.get_api_with_highest_rate_limit", return_value=("API", "TOKEN"))
mocker.patch(f"{base_import_path}.get_github_repo_api", return_value=Repository())

process_github_webhook = ProcessGithubWehook(
{"repository": {"name": Repository().name}}, Headers({"X-GitHub-Event": "test-event"}), logging.getLogger()
)
process_github_webhook.pull_request_branch = "main"
if hasattr(request, "param") and request.param:
process_github_webhook.changed_files = request.param[0]
else:
process_github_webhook.changed_files = ALL_CHANGED_FILES

return process_github_webhook
Loading