diff --git a/pr_agent/servers/github_app.py b/pr_agent/servers/github_app.py index eb726dd4..9a8784fd 100644 --- a/pr_agent/servers/github_app.py +++ b/pr_agent/servers/github_app.py @@ -141,10 +141,33 @@ async def handle_new_pr_opened(body: Dict[str, Any], ignore_pr_title_re = get_settings().get("GITHUB_APP.IGNORE_PR_TITLE", []) 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): get_logger().info(f"Ignoring PR with title '{title}' due to github_app.ignore_pr_title setting") return {} + # logic to ignore PRs with specific labels or source branches or target branches. + ignore_pr_labels = get_settings().get("GITHUB_APP.IGNORE_PR_LABELS", []) + ignore_pr_source_branches = get_settings().get("GITHUB_APP.IGNORE_PR_SOURCE_BRANCHES", []) + ignore_pr_target_branches = get_settings().get("GITHUB_APP.IGNORE_PR_TARGET_BRANCHES", []) + + if ignore_pr_labels: + labels = [label['name'] for label in pull_request.get("labels", [])] + if any(label in ignore_pr_labels for label in labels): + labels_str = ", ".join(labels) + get_logger().info(f"Ignoring PR with labels '{labels_str}' due to github_app.ignore_pr_labels settings") + return {} + + if ignore_pr_source_branches or ignore_pr_target_branches: + source_branch = pull_request.get("head", {}).get("ref", "") + target_branch = pull_request.get("base", {}).get("ref", "") + if any(re.search(regex, source_branch) for regex in ignore_pr_source_branches): + get_logger().info(f"Ignoring PR with source branch '{source_branch}' due to github_app.ignore_pr_source_branches settings") + return {} + if any(re.search(regex, target_branch) for regex in ignore_pr_target_branches): + get_logger().info(f"Ignoring PR with target branch '{target_branch}' due to github_app.ignore_pr_target_branches settings") + return {} + if get_identity_provider().verify_eligibility("github", sender_id, api_url) is not Eligibility.NOT_ELIGIBLE: await _perform_auto_commands_github("pr_commands", agent, body, api_url, log_context) else: diff --git a/pr_agent/servers/gitlab_webhook.py b/pr_agent/servers/gitlab_webhook.py index 3d72bc26..e57e3b8c 100644 --- a/pr_agent/servers/gitlab_webhook.py +++ b/pr_agent/servers/gitlab_webhook.py @@ -1,4 +1,5 @@ import copy +import re import json from datetime import datetime @@ -124,29 +125,48 @@ async def gitlab_webhook(background_tasks: BackgroundTasks, request: Request): return JSONResponse(status_code=status.HTTP_200_OK, content=jsonable_encoder({"message": "success"})) log_context["sender"] = sender - excluded_source_branches = get_settings().get("gitlab.excluded_source_branches", []) - excluded_target_branches = get_settings().get("gitlab.excluded_target_branches", []) - excluded_labels = get_settings().get("gitlab.excluded_labels", []) + if data.get('object_kind') == 'merge_request' and data['object_attributes'].get('action') in ['open', 'reopen']: + title = data['object_attributes'].get('title') url = data['object_attributes'].get('url') draft = data['object_attributes'].get('draft') - source_branch = data['object_attributes'].get('source_branch') - target_branch = data['object_attributes'].get('target_branch') - labels = [label['title'] for label in data['object_attributes'].get('labels', [])] get_logger().info(f"New merge request: {url}") - if target_branch in excluded_target_branches or source_branch in excluded_source_branches: - get_logger().info(f"Skipping excluded branch MR: {url}") - return JSONResponse(status_code=status.HTTP_200_OK, content=jsonable_encoder({"message": "success"})) - - if labels.intersection(excluded_labels): - get_logger().info(f"Skipping excluded label MR: {url}") - return JSONResponse(status_code=status.HTTP_200_OK, content=jsonable_encoder({"message": "success"})) + # ignore draft MRs. if draft: get_logger().info(f"Skipping draft MR: {url}") return JSONResponse(status_code=status.HTTP_200_OK, content=jsonable_encoder({"message": "success"})) + # logic to ignore MRs for titles, labels and source, target branches. + ignore_mr_title = get_settings().get("GITLAB.IGNORE_MR_TITLE", []) + ignore_mr_labels = get_settings().get("GITLAB.IGNORE_MR_LABELS", []) + ignore_mr_source_branches = get_settings().get("GITLAB.IGNORE_MR_SOURCE_BRANCHES", []) + ignore_mr_target_branches = get_settings().get("GITLAB.IGNORE_MR_TARGET_BRANCHES", []) + if ignore_mr_source_branches: + source_branch = data['object_attributes'].get('source_branch') + if any(re.search(regex, source_branch) for regex in ignore_mr_source_branches): + get_logger().info(f"Ignoring MR with source branch '{source_branch}' due to gitlab.ignore_mr_source_branches settings") + return JSONResponse(status_code=status.HTTP_200_OK, content=jsonable_encoder({"message": "success"})) + + if ignore_mr_target_branches: + target_branch = data['object_attributes'].get('target_branch') + if any(re.search(regex, target_branch) for regex in ignore_mr_target_branches): + get_logger().info(f"Ignoring MR with target branch '{target_branch}' due to gitlab.ignore_mr_target_branches settings") + return JSONResponse(status_code=status.HTTP_200_OK, content=jsonable_encoder({"message": "success"})) + + if ignore_mr_labels: + labels = [label['title'] for label in data['object_attributes'].get('labels', [])] + if any(label in ignore_mr_labels for label in labels): + labels_str = ", ".join(labels) + get_logger().info(f"Ignoring MR with labels '{labels_str}' due to gitlab.ignore_mr_labels settings") + return JSONResponse(status_code=status.HTTP_200_OK, content=jsonable_encoder({"message": "success"})) + + if ignore_mr_title: + if any([re.search(regex, title) for regex in ignore_mr_title]): + get_logger().info(f"Ignoring MR with title '{title}' due to gitlab.ignore_mr_title settings") + return JSONResponse(status_code=status.HTTP_200_OK, content=jsonable_encoder({"message": "success"})) + await _perform_commands_gitlab("pr_commands", PRAgent(), url, log_context) elif data.get('object_kind') == 'note' and data.get('event_type') == 'note': # comment on MR if 'merge_request' in data: diff --git a/pr_agent/settings/configuration.toml b/pr_agent/settings/configuration.toml index cd166180..e6d5968a 100644 --- a/pr_agent/settings/configuration.toml +++ b/pr_agent/settings/configuration.toml @@ -215,7 +215,15 @@ push_commands = [ "/describe", "/review --pr_reviewer.num_code_suggestions=0", ] +# a list of regular expressions to match against the PR title to ignore the PR agent ignore_pr_title = [] +# a list of regular expressions of target branches to ignore from PR agent when an MR is created +ignore_pr_target_branches = [] +# a list of regular expressions of source branches to ignore from PR agent when an MR is created +ignore_pr_source_branches = [] +# labels to ignore from PR agent when an MR is created +ignore_pr_labels = [] +# MR titles to ignore from PR agent when an MR is created ignore_bot_pr = true [gitlab] @@ -230,9 +238,14 @@ push_commands = [ "/describe", "/review --pr_reviewer.num_code_suggestions=0", ] -excluded_target_branches = [] -excluded_source_branches = [] -excluded_labels = [] +# a list of regular expressions to match against the PR title to ignore the PR agent +ignore_mr_title = [] +# target branches to ignore from PR agent when an MR is created +ignore_mr_target_branches = [] +# source branches to ignore from PR agent when an MR is created +ignore_mr_source_branches = [] +# labels to ignore from PR agent when an MR is created +ignore_mr_labels = [] [bitbucket_app] pr_commands = [