mirror of
https://github.com/qodo-ai/pr-agent.git
synced 2025-07-05 13:20:39 +08:00
Merge branch 'main' into feature/valid-file-filter-log
This commit is contained in:
@ -1,13 +1,13 @@
|
|||||||
import json
|
import json
|
||||||
from typing import Optional, Tuple
|
from typing import Optional, Tuple
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import quote_plus, urlparse
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from atlassian.bitbucket import Bitbucket
|
from atlassian.bitbucket import Bitbucket
|
||||||
from starlette_context import context
|
from starlette_context import context
|
||||||
|
|
||||||
from .git_provider import GitProvider
|
from .git_provider import GitProvider
|
||||||
from pr_agent.algo.types import FilePatchInfo
|
from ..algo.types import EDIT_TYPE, FilePatchInfo
|
||||||
from ..algo.language_handler import is_valid_file
|
from ..algo.language_handler import is_valid_file
|
||||||
from ..algo.utils import load_large_diff, find_line_number_of_relevant_line_in_file
|
from ..algo.utils import load_large_diff, find_line_number_of_relevant_line_in_file
|
||||||
from ..config_loader import get_settings
|
from ..config_loader import get_settings
|
||||||
@ -60,6 +60,9 @@ class BitbucketServerProvider(GitProvider):
|
|||||||
except Exception:
|
except Exception:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
def get_pr_id(self):
|
||||||
|
return self.pr_num
|
||||||
|
|
||||||
def publish_code_suggestions(self, code_suggestions: list) -> bool:
|
def publish_code_suggestions(self, code_suggestions: list) -> bool:
|
||||||
"""
|
"""
|
||||||
Publishes code suggestions as comments on the PR.
|
Publishes code suggestions as comments on the PR.
|
||||||
@ -141,14 +144,8 @@ class BitbucketServerProvider(GitProvider):
|
|||||||
if self.diff_files:
|
if self.diff_files:
|
||||||
return self.diff_files
|
return self.diff_files
|
||||||
|
|
||||||
commits_in_pr = self.bitbucket_client.get_pull_requests_commits(
|
base_sha = self.pr.toRef['latestCommit']
|
||||||
self.workspace_slug,
|
head_sha = self.pr.fromRef['latestCommit']
|
||||||
self.repo_slug,
|
|
||||||
self.pr_num
|
|
||||||
)
|
|
||||||
|
|
||||||
commit_list = list(commits_in_pr)
|
|
||||||
base_sha, head_sha = commit_list[0]['parents'][0]['id'], commit_list[-1]['id']
|
|
||||||
|
|
||||||
diff_files = []
|
diff_files = []
|
||||||
original_file_content_str = ""
|
original_file_content_str = ""
|
||||||
@ -246,8 +243,11 @@ class BitbucketServerProvider(GitProvider):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
response = requests.post(url=self._get_pr_comments_url(), json=payload, headers=self.headers)
|
try:
|
||||||
return response
|
requests.post(url=self._get_pr_comments_url(), json=payload, headers=self.headers).raise_for_status()
|
||||||
|
except Exception as e:
|
||||||
|
get_logger().error(f"Failed to publish inline comment to '{file}' at line {from_line}, error: {e}")
|
||||||
|
raise e
|
||||||
|
|
||||||
def generate_link_to_relevant_line_number(self, suggestion) -> str:
|
def generate_link_to_relevant_line_number(self, suggestion) -> str:
|
||||||
try:
|
try:
|
||||||
@ -260,18 +260,37 @@ class BitbucketServerProvider(GitProvider):
|
|||||||
position, absolute_position = find_line_number_of_relevant_line_in_file \
|
position, absolute_position = find_line_number_of_relevant_line_in_file \
|
||||||
(diff_files, relevant_file, relevant_line_str)
|
(diff_files, relevant_file, relevant_line_str)
|
||||||
|
|
||||||
|
if absolute_position != -1:
|
||||||
|
if self.pr:
|
||||||
|
link = f"{self.pr_url}/diff#{quote_plus(relevant_file)}?t={absolute_position}"
|
||||||
|
return link
|
||||||
|
else:
|
||||||
|
if get_settings().config.verbosity_level >= 2:
|
||||||
|
get_logger().info(f"Failed adding line link to '{relevant_file}' since PR not set")
|
||||||
|
else:
|
||||||
|
if get_settings().config.verbosity_level >= 2:
|
||||||
|
get_logger().info(f"Failed adding line link to '{relevant_file}' since position not found")
|
||||||
|
|
||||||
if absolute_position != -1 and self.pr_url:
|
if absolute_position != -1 and self.pr_url:
|
||||||
link = f"{self.pr_url}/#L{relevant_file}T{absolute_position}"
|
link = f"{self.pr_url}/diff#{quote_plus(relevant_file)}?t={absolute_position}"
|
||||||
return link
|
return link
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if get_settings().config.verbosity_level >= 2:
|
if get_settings().config.verbosity_level >= 2:
|
||||||
get_logger().info(f"Failed adding line link, error: {e}")
|
get_logger().info(f"Failed adding line link to '{relevant_file}', error: {e}")
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def publish_inline_comments(self, comments: list[dict]):
|
def publish_inline_comments(self, comments: list[dict]):
|
||||||
for comment in comments:
|
for comment in comments:
|
||||||
|
if 'position' in comment:
|
||||||
self.publish_inline_comment(comment['body'], comment['position'], comment['path'])
|
self.publish_inline_comment(comment['body'], comment['position'], comment['path'])
|
||||||
|
elif 'start_line' in comment: # multi-line comment
|
||||||
|
# note that bitbucket does not seem to support range - only a comment on a single line - https://community.developer.atlassian.com/t/api-post-endpoint-for-inline-pull-request-comments/60452
|
||||||
|
self.publish_inline_comment(comment['body'], comment['start_line'], comment['path'])
|
||||||
|
elif 'line' in comment: # single-line comment
|
||||||
|
self.publish_inline_comment(comment['body'], comment['line'], comment['path'])
|
||||||
|
else:
|
||||||
|
get_logger().error(f"Could not publish inline comment: {comment}")
|
||||||
|
|
||||||
def get_title(self):
|
def get_title(self):
|
||||||
return self.pr.title
|
return self.pr.title
|
||||||
@ -283,7 +302,10 @@ class BitbucketServerProvider(GitProvider):
|
|||||||
return self.pr.fromRef['displayId']
|
return self.pr.fromRef['displayId']
|
||||||
|
|
||||||
def get_pr_description_full(self):
|
def get_pr_description_full(self):
|
||||||
|
if hasattr(self.pr, "description"):
|
||||||
return self.pr.description
|
return self.pr.description
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
def get_user_id(self):
|
def get_user_id(self):
|
||||||
return 0
|
return 0
|
||||||
@ -310,7 +332,7 @@ class BitbucketServerProvider(GitProvider):
|
|||||||
path_parts = parsed_url.path.strip("/").split("/")
|
path_parts = parsed_url.path.strip("/").split("/")
|
||||||
if len(path_parts) < 6 or path_parts[4] != "pull-requests":
|
if len(path_parts) < 6 or path_parts[4] != "pull-requests":
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"The provided URL does not appear to be a Bitbucket PR URL"
|
f"The provided URL '{pr_url}' does not appear to be a Bitbucket PR URL"
|
||||||
)
|
)
|
||||||
|
|
||||||
workspace_slug = path_parts[1]
|
workspace_slug = path_parts[1]
|
||||||
@ -318,7 +340,7 @@ class BitbucketServerProvider(GitProvider):
|
|||||||
try:
|
try:
|
||||||
pr_number = int(path_parts[5])
|
pr_number = int(path_parts[5])
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise ValueError("Unable to convert PR number to integer") from e
|
raise ValueError(f"Unable to convert PR number '{path_parts[5]}' to integer") from e
|
||||||
|
|
||||||
return workspace_slug, repo_slug, pr_number
|
return workspace_slug, repo_slug, pr_number
|
||||||
|
|
||||||
@ -339,13 +361,18 @@ class BitbucketServerProvider(GitProvider):
|
|||||||
raise NotImplementedError("Get commit messages function not implemented yet.")
|
raise NotImplementedError("Get commit messages function not implemented yet.")
|
||||||
# bitbucket does not support labels
|
# bitbucket does not support labels
|
||||||
def publish_description(self, pr_title: str, description: str):
|
def publish_description(self, pr_title: str, description: str):
|
||||||
payload = json.dumps({
|
payload = {
|
||||||
|
"version": self.pr.version,
|
||||||
"description": description,
|
"description": description,
|
||||||
"title": pr_title
|
"title": pr_title,
|
||||||
})
|
"reviewers": self.pr.reviewers # needs to be sent otherwise gets wiped
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
self.bitbucket_client.update_pull_request(self.workspace_slug, self.repo_slug, str(self.pr_num), payload)
|
||||||
|
except Exception as e:
|
||||||
|
get_logger().error(f"Failed to update pull request, error: {e}")
|
||||||
|
raise e
|
||||||
|
|
||||||
response = requests.put(url=self.bitbucket_pull_request_api_url, headers=self.headers, data=payload)
|
|
||||||
return response
|
|
||||||
|
|
||||||
# bitbucket does not support labels
|
# bitbucket does not support labels
|
||||||
def publish_labels(self, pr_types: list):
|
def publish_labels(self, pr_types: list):
|
||||||
|
Reference in New Issue
Block a user