mirror of
https://github.com/qodo-ai/pr-agent.git
synced 2025-07-03 04:10:49 +08:00
Add ignore_repositories config for PR filtering
What Changed? * Added support to ignore PRs/MRs from specific repositories in GitHub, Bitbucket, and GitLab webhook logic * Updated configuration.toml to include ignore_repositories option * Added unit tests for ignore_repositories across all supported providers
This commit is contained in:
@ -127,11 +127,22 @@ def should_process_pr_logic(data) -> bool:
|
||||
source_branch = pr_data.get("source", {}).get("branch", {}).get("name", "")
|
||||
target_branch = pr_data.get("destination", {}).get("branch", {}).get("name", "")
|
||||
sender = _get_username(data)
|
||||
repo_full_name = pr_data.get("destination", {}).get("repository", {}).get("full_name", "")
|
||||
|
||||
print(f"DEBUG: repo_full_name={repo_full_name}, ignore_repos={get_settings().get('CONFIG.IGNORE_REPOSITORIES', [])}")
|
||||
# logic to ignore PRs from specific repositories
|
||||
ignore_repos = get_settings().get("CONFIG.IGNORE_REPOSITORIES", [])
|
||||
if ignore_repos and repo_full_name:
|
||||
if repo_full_name in ignore_repos:
|
||||
print(f"DEBUG: Ignoring due to repo match: {repo_full_name}")
|
||||
get_logger().info(f"Ignoring PR from repository '{repo_full_name}' due to 'config.ignore_repositories' setting")
|
||||
return False
|
||||
|
||||
# logic to ignore PRs from specific users
|
||||
ignore_pr_users = get_settings().get("CONFIG.IGNORE_PR_AUTHORS", [])
|
||||
if ignore_pr_users and sender:
|
||||
if sender in ignore_pr_users:
|
||||
print(f"DEBUG: Ignoring due to user match: {sender}")
|
||||
get_logger().info(f"Ignoring PR from user '{sender}' due to 'config.ignore_pr_authors' setting")
|
||||
return False
|
||||
|
||||
@ -141,6 +152,7 @@ def should_process_pr_logic(data) -> bool:
|
||||
if not isinstance(ignore_pr_title_re, list):
|
||||
ignore_pr_title_re = [ignore_pr_title_re]
|
||||
if ignore_pr_title_re and any(re.search(regex, title) for regex in ignore_pr_title_re):
|
||||
print(f"DEBUG: Ignoring due to title match: {title}")
|
||||
get_logger().info(f"Ignoring PR with title '{title}' due to config.ignore_pr_title setting")
|
||||
return False
|
||||
|
||||
@ -148,15 +160,19 @@ def should_process_pr_logic(data) -> bool:
|
||||
ignore_pr_target_branches = get_settings().get("CONFIG.IGNORE_PR_TARGET_BRANCHES", [])
|
||||
if (ignore_pr_source_branches or ignore_pr_target_branches):
|
||||
if any(re.search(regex, source_branch) for regex in ignore_pr_source_branches):
|
||||
print(f"DEBUG: Ignoring due to source branch match: {source_branch}")
|
||||
get_logger().info(
|
||||
f"Ignoring PR with source branch '{source_branch}' due to config.ignore_pr_source_branches settings")
|
||||
return False
|
||||
if any(re.search(regex, target_branch) for regex in ignore_pr_target_branches):
|
||||
print(f"DEBUG: Ignoring due to target branch match: {target_branch}")
|
||||
get_logger().info(
|
||||
f"Ignoring PR with target branch '{target_branch}' due to config.ignore_pr_target_branches settings")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"DEBUG: Exception in should_process_pr_logic: {e}")
|
||||
get_logger().error(f"Failed 'should_process_pr_logic': {e}")
|
||||
print("DEBUG: Returning True from should_process_pr_logic")
|
||||
return True
|
||||
|
||||
|
||||
|
@ -258,6 +258,14 @@ def should_process_pr_logic(body) -> bool:
|
||||
source_branch = pull_request.get("head", {}).get("ref", "")
|
||||
target_branch = pull_request.get("base", {}).get("ref", "")
|
||||
sender = body.get("sender", {}).get("login")
|
||||
repo_full_name = body.get("repository", {}).get("full_name", "")
|
||||
|
||||
# logic to ignore PRs from specific repositories
|
||||
ignore_repos = get_settings().get("CONFIG.IGNORE_REPOSITORIES", [])
|
||||
if ignore_repos and repo_full_name:
|
||||
if repo_full_name in ignore_repos:
|
||||
get_logger().info(f"Ignoring PR from repository '{repo_full_name}' due to 'config.ignore_repositories' setting")
|
||||
return False
|
||||
|
||||
# logic to ignore PRs from specific users
|
||||
ignore_pr_users = get_settings().get("CONFIG.IGNORE_PR_AUTHORS", [])
|
||||
|
@ -103,6 +103,14 @@ def should_process_pr_logic(data) -> bool:
|
||||
return False
|
||||
title = data['object_attributes'].get('title')
|
||||
sender = data.get("user", {}).get("username", "")
|
||||
repo_full_name = data.get('project', {}).get('path_with_namespace', "")
|
||||
|
||||
# logic to ignore PRs from specific repositories
|
||||
ignore_repos = get_settings().get("CONFIG.IGNORE_REPOSITORIES", [])
|
||||
if ignore_repos and repo_full_name:
|
||||
if repo_full_name in ignore_repos:
|
||||
get_logger().info(f"Ignoring MR from repository '{repo_full_name}' due to 'config.ignore_repositories' setting")
|
||||
return False
|
||||
|
||||
# logic to ignore PRs from specific users
|
||||
ignore_pr_users = get_settings().get("CONFIG.IGNORE_PR_AUTHORS", [])
|
||||
|
@ -55,6 +55,7 @@ ignore_pr_target_branches = [] # a list of regular expressions of target branche
|
||||
ignore_pr_source_branches = [] # a list of regular expressions of source branches to ignore from PR agent when an PR is created
|
||||
ignore_pr_labels = [] # labels to ignore from PR agent when an PR is created
|
||||
ignore_pr_authors = [] # authors to ignore from PR agent when an PR is created
|
||||
ignore_repositories = [] # list of repository full names (e.g. "org/repo") to ignore from PR agent processing
|
||||
#
|
||||
is_auto_command = false # will be auto-set to true if the command is triggered by an automation
|
||||
enable_ai_metadata = false # will enable adding ai metadata
|
||||
|
79
tests/unittest/test_ignore_repositories.py
Normal file
79
tests/unittest/test_ignore_repositories.py
Normal file
@ -0,0 +1,79 @@
|
||||
import pytest
|
||||
from pr_agent.servers.github_app import should_process_pr_logic as github_should_process_pr_logic
|
||||
from pr_agent.servers.bitbucket_app import should_process_pr_logic as bitbucket_should_process_pr_logic
|
||||
from pr_agent.servers.gitlab_webhook import should_process_pr_logic as gitlab_should_process_pr_logic
|
||||
from pr_agent.config_loader import get_settings
|
||||
|
||||
def make_bitbucket_payload(full_name):
|
||||
return {
|
||||
"data": {
|
||||
"pullrequest": {
|
||||
"title": "Test PR",
|
||||
"source": {"branch": {"name": "feature/test"}},
|
||||
"destination": {
|
||||
"branch": {"name": "main"},
|
||||
"repository": {"full_name": full_name}
|
||||
}
|
||||
},
|
||||
"actor": {"username": "user", "type": "user"}
|
||||
}
|
||||
}
|
||||
|
||||
def make_github_body(full_name):
|
||||
return {
|
||||
"pull_request": {},
|
||||
"repository": {"full_name": full_name},
|
||||
"sender": {"login": "user"}
|
||||
}
|
||||
|
||||
def make_gitlab_body(full_name):
|
||||
return {
|
||||
"object_attributes": {"title": "Test MR"},
|
||||
"project": {"path_with_namespace": full_name}
|
||||
}
|
||||
|
||||
PROVIDERS = [
|
||||
("github", github_should_process_pr_logic, make_github_body),
|
||||
("bitbucket", bitbucket_should_process_pr_logic, make_bitbucket_payload),
|
||||
("gitlab", gitlab_should_process_pr_logic, make_gitlab_body),
|
||||
]
|
||||
|
||||
class TestIgnoreRepositories:
|
||||
def setup_method(self):
|
||||
get_settings().set("CONFIG.IGNORE_REPOSITORIES", [])
|
||||
|
||||
@pytest.mark.parametrize("provider_name, provider_func, body_func", PROVIDERS)
|
||||
def test_should_ignore_matching_repository(self, provider_name, provider_func, body_func):
|
||||
get_settings().set("CONFIG.IGNORE_REPOSITORIES", ["org/repo-to-ignore"])
|
||||
body = {
|
||||
"pull_request": {},
|
||||
"repository": {"full_name": "org/repo-to-ignore"},
|
||||
"sender": {"login": "user"}
|
||||
}
|
||||
result = provider_func(body_func(body["repository"]["full_name"]))
|
||||
print(f"DEBUG: Provider={provider_name}, test_should_ignore_matching_repository, result={result}")
|
||||
assert result is False, f"{provider_name}: PR from ignored repository should be ignored (return False)"
|
||||
|
||||
@pytest.mark.parametrize("provider_name, provider_func, body_func", PROVIDERS)
|
||||
def test_should_not_ignore_non_matching_repository(self, provider_name, provider_func, body_func):
|
||||
get_settings().set("CONFIG.IGNORE_REPOSITORIES", ["org/repo-to-ignore"])
|
||||
body = {
|
||||
"pull_request": {},
|
||||
"repository": {"full_name": "org/other-repo"},
|
||||
"sender": {"login": "user"}
|
||||
}
|
||||
result = provider_func(body_func(body["repository"]["full_name"]))
|
||||
print(f"DEBUG: Provider={provider_name}, test_should_not_ignore_non_matching_repository, result={result}")
|
||||
assert result is True, f"{provider_name}: PR from non-ignored repository should not be ignored (return True)"
|
||||
|
||||
@pytest.mark.parametrize("provider_name, provider_func, body_func", PROVIDERS)
|
||||
def test_should_not_ignore_when_config_empty(self, provider_name, provider_func, body_func):
|
||||
get_settings().set("CONFIG.IGNORE_REPOSITORIES", [])
|
||||
body = {
|
||||
"pull_request": {},
|
||||
"repository": {"full_name": "org/repo-to-ignore"},
|
||||
"sender": {"login": "user"}
|
||||
}
|
||||
result = provider_func(body_func(body["repository"]["full_name"]))
|
||||
print(f"DEBUG: Provider={provider_name}, test_should_not_ignore_when_config_empty, result={result}")
|
||||
assert result is True, f"{provider_name}: PR should not be ignored if ignore_repositories config is empty"
|
Reference in New Issue
Block a user