Skip to content

Commit

Permalink
feat: add support for ignoring PRs from specific users
Browse files Browse the repository at this point in the history
  • Loading branch information
mrT23 committed Jan 16, 2025
1 parent 1997da3 commit 4923c8d
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 15 deletions.
46 changes: 45 additions & 1 deletion docs/docs/usage-guide/additional_configurations.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,17 @@ LANGSMITH_BASE_URL=<url>

## Ignoring automatic commands in PRs

In some cases, you may want to automatically ignore specific PRs . Qodo Merge enables you to ignore PR with a specific title, or from/to specific branches (regex matching).
Qodo Merge allows you to automatically ignore certain PRs based on various criteria:

- PRs with specific titles (using regex matching)
- PRs between specific branches (using regex matching)
- PRs that don't include changes from specific folders (using regex matching)
- PRs containing specific labels
- PRs opened by specific users

### Example usage

#### Ignoring PRs with specific titles

To ignore PRs with a specific title such as "[Bump]: ...", you can add the following to your `configuration.toml` file:

Expand All @@ -149,6 +159,7 @@ ignore_pr_title = ["\\[Bump\\]"]

Where the `ignore_pr_title` is a list of regex patterns to match the PR title you want to ignore. Default is `ignore_pr_title = ["^\\[Auto\\]", "^Auto"]`.

#### Ignoring PRs between specific branches

To ignore PRs from specific source or target branches, you can add the following to your `configuration.toml` file:

Expand All @@ -161,6 +172,7 @@ ignore_pr_target_branches = ["qa"]
Where the `ignore_pr_source_branches` and `ignore_pr_target_branches` are lists of regex patterns to match the source and target branches you want to ignore.
They are not mutually exclusive, you can use them together or separately.

#### Ignoring PRs that don't include changes from specific folders

To allow only specific folders (often needed in large monorepos), set:

Expand All @@ -170,3 +182,35 @@ allow_only_specific_folders=['folder1','folder2']
```

For the configuration above, automatic feedback will only be triggered when the PR changes include files from 'folder1' or 'folder2'

#### Ignoring PRs containg specific labels

To ignore PRs containg specific labels, you can add the following to your `configuration.toml` file:

```
[config]
ignore_pr_labels = ["do-not-merge"]
```

Where the `ignore_pr_labels` is a list of labels that when present in the PR, the PR will be ignored.

#### Ignoring PRs from specific users

Qodo Merge automatically identifies and ignores pull requests created by bots using:

- GitHub's native bot detection system
- Name-based pattern matching

While this detection is robust, it may not catch all cases, particularly when:

- Bots are registered as regular user accounts
- Bot names don't match common patterns

To supplement the automatic bot detection, you can manually specify users to ignore. Add the following to your `configuration.toml` file to ignore PRs from specific users:
```
[config]
ignore_pr_authors = ["my-special-bot-user", ...]
```

Where the `ignore_pr_authors` is a list of usernames that you want to ignore.

35 changes: 21 additions & 14 deletions pr_agent/servers/bitbucket_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@
from pr_agent.identity_providers.identity_provider import Eligibility
from pr_agent.log import LoggingFormat, get_logger, setup_logger
from pr_agent.secret_providers import get_secret_provider
from pr_agent.servers.github_action_runner import get_setting_or_env, is_true
from pr_agent.tools.pr_code_suggestions import PRCodeSuggestions
from pr_agent.tools.pr_description import PRDescription
from pr_agent.tools.pr_reviewer import PRReviewer

setup_logger(fmt=LoggingFormat.JSON, level="DEBUG")
router = APIRouter()
Expand Down Expand Up @@ -75,6 +71,18 @@ async def handle_manifest(request: Request, response: Response):
return JSONResponse(manifest_obj)


def _get_username(data):
actor = data.get("data", {}).get("actor", {})
if actor:
if "username" in actor:
return actor["username"]
elif "display_name" in actor:
return actor["display_name"]
elif "nickname" in actor:
return actor["nickname"]
return ""


async def _perform_commands_bitbucket(commands_conf: str, agent: PRAgent, api_url: str, log_context: dict, data: dict):
apply_repo_settings(api_url)
if commands_conf == "pr_commands" and get_settings().config.disable_auto_feedback: # auto commands for PR, and auto feedback is disabled
Expand Down Expand Up @@ -118,6 +126,14 @@ def should_process_pr_logic(data) -> bool:
title = pr_data.get("title", "")
source_branch = pr_data.get("source", {}).get("branch", {}).get("name", "")
target_branch = pr_data.get("destination", {}).get("branch", {}).get("name", "")
sender = _get_username(data)

# 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:
get_logger().info(f"Ignoring PR from user '{sender}' due to 'config.ignore_pr_authors' setting")
return False

# logic to ignore PRs with specific titles
if title:
Expand Down Expand Up @@ -167,16 +183,7 @@ async def inner():
return "OK"

# Get the username of the sender
actor = data.get("data", {}).get("actor", {})
if actor:
try:
username = actor["username"]
except KeyError:
try:
username = actor["display_name"]
except KeyError:
username = actor["nickname"]
log_context["sender"] = username
log_context["sender"] = _get_username(data)

sender_id = data.get("data", {}).get("actor", {}).get("account_id", "")
log_context["sender_id"] = sender_id
Expand Down
9 changes: 9 additions & 0 deletions pr_agent/servers/github_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,14 @@ def should_process_pr_logic(body) -> bool:
pr_labels = pull_request.get("labels", [])
source_branch = pull_request.get("head", {}).get("ref", "")
target_branch = pull_request.get("base", {}).get("ref", "")
sender = body.get("sender", {}).get("login")

# 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:
get_logger().info(f"Ignoring PR from user '{sender}' due to 'config.ignore_pr_authors' setting")
return False

# logic to ignore PRs with specific titles
if title:
Expand All @@ -276,6 +284,7 @@ def should_process_pr_logic(body) -> bool:
get_logger().info(f"Ignoring PR with labels '{labels_str}' due to config.ignore_pr_labels settings")
return False

# logic to ignore PRs with specific source or target branches
ignore_pr_source_branches = get_settings().get("CONFIG.IGNORE_PR_SOURCE_BRANCHES", [])
ignore_pr_target_branches = get_settings().get("CONFIG.IGNORE_PR_TARGET_BRANCHES", [])
if pull_request and (ignore_pr_source_branches or ignore_pr_target_branches):
Expand Down
8 changes: 8 additions & 0 deletions pr_agent/servers/gitlab_webhook.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,14 @@ def should_process_pr_logic(data) -> bool:
if not data.get('object_attributes', {}):
return False
title = data['object_attributes'].get('title')
sender = data.get("user", {}).get("username", "")

# 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:
get_logger().info(f"Ignoring PR from user '{sender}' due to 'config.ignore_pr_authors' settings")
return False

# logic to ignore MRs for titles, labels and source, target branches.
ignore_mr_title = get_settings().get("CONFIG.IGNORE_PR_TITLE", [])
Expand Down
1 change: 1 addition & 0 deletions pr_agent/settings/configuration.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ ignore_pr_title = ["^\\[Auto\\]", "^Auto"] # a list of regular expressions to ma
ignore_pr_target_branches = [] # a list of regular expressions of target branches to ignore from PR agent when an PR is created
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
#
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
Expand Down

0 comments on commit 4923c8d

Please sign in to comment.