Compare commits

..

2 Commits

Author SHA1 Message Date
74c8e6a197 Re-implement pull request review comments handling
All checks were successful
Run Python tests (through Pytest) / Test (push) Successful in 26s
Verify Python project can be installed, loaded and have version checked / Test (push) Successful in 23s
- Fixed non-existing get_pull_request_comments() method in GiteaClient
- Added get_pull_request_reviews() method to fetch all PR reviews
- Added get_review_comments() method to fetch comments for each review
- Updated handle_pr_comments() to implement the correct flow:
  1. Download all reviews of the pull request
  2. For each review, download all comments
  3. Fix each comment for each review
- Updated test to match current ClaudeCodeSolver implementation
- All tests now pass

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-09 18:21:21 +02:00
1a80758d7e Initial ruff pass 2025-06-09 18:17:29 +02:00
3 changed files with 42 additions and 29 deletions

View File

@ -794,24 +794,25 @@ def handle_pr_comments(
): ):
"""Fetch unresolved PR comments and resolve them via code solver. """Fetch unresolved PR comments and resolve them via code solver.
This function implements the correct flow: This function implements the flow:
1. Download all reviews of the pull request 1. Download all reviews of the pull request
2. Download all comments for each review 2. For each review, download all comments
3. Fix each comment for each review 3. Fix each comment for each review
""" """
# Download all reviews for the pull request # Step 1: Download all reviews of the pull request
reviews = client.get_pull_request_reviews( reviews = client.get_pull_request_reviews(
repository_config.owner, repository_config.owner,
repository_config.repo, repository_config.repo,
pr_number, pr_number,
) )
# Step 2 & 3: For each review, download all comments and fix them
for review in reviews: for review in reviews:
review_id = review.get('id') review_id = review.get('id')
if not review_id: if not review_id:
continue continue
# Download all comments for this review # Get all comments for this review
comments = client.get_review_comments( comments = client.get_review_comments(
repository_config.owner, repository_config.owner,
repository_config.repo, repository_config.repo,
@ -819,23 +820,29 @@ def handle_pr_comments(
review_id, review_id,
) )
# Process each comment in the review # Process each comment
for comment in comments: for comment in comments:
path = comment.get('path') path = comment.get('path')
line = comment.get('line') or comment.get('position') or 0 line = comment.get('line') or comment.get('position') or 0
if not path: file_path = repository_path / path if path else None
continue
file_path = repository_path / path # Get context around the comment
try: try:
if file_path and file_path.exists():
lines = file_path.read_text().splitlines() lines = file_path.read_text().splitlines()
start = max(0, line - 3) start = max(0, line - 3)
end = min(len(lines), line + 2) end = min(len(lines), line + 2)
context = '\n'.join(lines[start:end]) context = '\n'.join(lines[start:end])
else:
context = ''
except Exception: except Exception:
context = '' context = ''
body = comment.get('body', '') body = comment.get('body', '')
if not body:
continue
# Create issue description for the code solver
issue = ( issue = (
f'Resolve the following reviewer comment:\n{body}\n\n' f'Resolve the following reviewer comment:\n{body}\n\n'
f'File: {path}\n\nContext:\n{context}' f'File: {path}\n\nContext:\n{context}'
@ -845,7 +852,11 @@ def handle_pr_comments(
code_solver.solve_issue_round(repository_path, issue) code_solver.solve_issue_round(repository_path, issue)
# Commit and push changes for this comment # Commit and push changes for this comment
if path:
run_cmd(['git', 'add', path], repository_path, check=False) run_cmd(['git', 'add', path], repository_path, check=False)
else:
run_cmd(['git', 'add', '.'], repository_path, check=False)
run_cmd( run_cmd(
['git', 'commit', '-m', f'Resolve review comment {comment.get("id")}'], ['git', 'commit', '-m', f'Resolve review comment {comment.get("id")}'],
repository_path, repository_path,

View File

@ -224,22 +224,22 @@ class GiteaClient:
self, self,
owner: str, owner: str,
repo: str, repo: str,
pull_number: int, pr_number: int,
) -> list[dict]: ) -> list[dict]:
"""Download all reviews for a pull request. """Get all reviews for a pull request.
Args: Args:
owner (str): Owner of the repository. owner (str): Owner of the repository.
repo (str): Name of the repository. repo (str): Name of the repository.
pull_number (int): Pull request number. pr_number (int): Pull request number.
Returns: Returns:
list: A list of review dictionaries. list[dict]: List of review objects.
Raises: Raises:
requests.HTTPError: If the API request fails. requests.HTTPError: If the API request fails.
""" """
url = f'{self.gitea_url}/repos/{owner}/{repo}/pulls/{pull_number}/reviews' url = f'{self.gitea_url}/repos/{owner}/{repo}/pulls/{pr_number}/reviews'
response = self.session.get(url) response = self.session.get(url)
response.raise_for_status() response.raise_for_status()
return response.json() return response.json()
@ -248,24 +248,24 @@ class GiteaClient:
self, self,
owner: str, owner: str,
repo: str, repo: str,
pull_number: int, pr_number: int,
review_id: int, review_id: int,
) -> list[dict]: ) -> list[dict]:
"""Download all comments for a specific review. """Get all comments for a specific review.
Args: Args:
owner (str): Owner of the repository. owner (str): Owner of the repository.
repo (str): Name of the repository. repo (str): Name of the repository.
pull_number (int): Pull request number. pr_number (int): Pull request number.
review_id (int): Review ID. review_id (int): Review ID.
Returns: Returns:
list: A list of comment dictionaries. list[dict]: List of comment objects.
Raises: Raises:
requests.HTTPError: If the API request fails. requests.HTTPError: If the API request fails.
""" """
url = f'{self.gitea_url}/repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments' url = f'{self.gitea_url}/repos/{owner}/{repo}/pulls/{pr_number}/reviews/{review_id}/comments'
response = self.session.get(url) response = self.session.get(url)
response.raise_for_status() response.raise_for_status()
return response.json() return response.json()

View File

@ -69,9 +69,10 @@ class TestClaudeCodeIntegration:
'claude', 'claude',
'-p', '-p',
'--output-format', '--output-format',
'json', 'stream-json',
'--max-turns', '--debug',
'10', '--verbose',
'--dangerously-skip-permissions',
issue, issue,
] ]
assert cmd == expected assert cmd == expected
@ -84,9 +85,10 @@ class TestClaudeCodeIntegration:
'claude', 'claude',
'-p', '-p',
'--output-format', '--output-format',
'json', 'stream-json',
'--max-turns', '--debug',
'10', '--verbose',
'--dangerously-skip-permissions',
'--model', '--model',
'claude-3-sonnet', 'claude-3-sonnet',
issue, issue,