From 351817d6c7a1fe67f6ba35e2051458c21beca7ec Mon Sep 17 00:00:00 2001 From: "Jon Michael Aanes (aider)" Date: Tue, 15 Apr 2025 23:37:19 +0200 Subject: [PATCH] feat: Add issue commenting for PR creation and push failures --- aider_gitea/__init__.py | 51 ++++++++++++---- aider_gitea/gitea_client.py | 22 +++++++ test/test_issue_comment_on_failure.py | 83 +++++++++++++++++++++++++++ 3 files changed, 145 insertions(+), 11 deletions(-) create mode 100644 test/test_issue_comment_on_failure.py diff --git a/aider_gitea/__init__.py b/aider_gitea/__init__.py index 2ba421e..1cb87bc 100644 --- a/aider_gitea/__init__.py +++ b/aider_gitea/__init__.py @@ -229,19 +229,48 @@ def push_changes( # First push the branch without creating a PR cmd = ['git', 'push', 'origin', branch_name, '--force'] - run_cmd(cmd, cwd) + push_success = run_cmd(cmd, cwd, check=False) + + if not push_success: + error_message = f"Failed to push branch `{branch_name}`. The changes could not be uploaded to the repository." + logger.error(error_message) + try: + gitea_client.create_issue_comment( + owner=owner, + repo=repo, + issue_number=issue_number, + body=f"❌ **Automated Solution Failed**\n\n{error_message}\n\nPlease check repository permissions and try again." + ) + except Exception as e: + logger.exception(f"Failed to comment on issue #{issue_number} after push failure: {e}") + return False # Then create the PR with the aider label - gitea_client.create_pull_request( - owner=owner, - repo=repo, - title=issue_title, - body=description, - head=branch_name, - base=base_branch, - labels=['aider'], - ) - return True + try: + gitea_client.create_pull_request( + owner=owner, + repo=repo, + title=issue_title, + body=description, + head=branch_name, + base=base_branch, + labels=['aider'], + ) + return True + except Exception as e: + error_message = f"Failed to create pull request for branch `{branch_name}`. The changes were pushed but the PR could not be created." + logger.exception(f"{error_message}: {e}") + try: + gitea_client.create_issue_comment( + owner=owner, + repo=repo, + issue_number=issue_number, + body=f"⚠️ **Partial Automation Success**\n\n{error_message}\n\n" + f"The changes are available in the branch `{branch_name}`, but you'll need to create the PR manually." + ) + except Exception as comment_error: + logger.exception(f"Failed to comment on issue #{issue_number} after PR creation failure: {comment_error}") + return False def has_commits_on_branch(cwd: Path, base_branch: str, current_branch: str) -> bool: diff --git a/aider_gitea/gitea_client.py b/aider_gitea/gitea_client.py index d392cab..0207ade 100644 --- a/aider_gitea/gitea_client.py +++ b/aider_gitea/gitea_client.py @@ -168,3 +168,25 @@ class GiteaClient: response = self.session.post(url, json=json_data) response.raise_for_status() return response.json() + + def create_issue_comment(self, owner: str, repo: str, issue_number: str, body: str) -> dict: + """Create a comment on an issue. + + Args: + owner (str): Owner of the repository. + repo (str): Name of the repository. + issue_number (str): The issue number to comment on. + body (str): The content of the comment. + + Returns: + dict: The created comment data. + + Raises: + requests.HTTPError: If the API request fails. + """ + url = f'{self.gitea_url}/repos/{owner}/{repo}/issues/{issue_number}/comments' + json_data = {'body': body} + + response = self.session.post(url, json=json_data) + response.raise_for_status() + return response.json() diff --git a/test/test_issue_comment_on_failure.py b/test/test_issue_comment_on_failure.py new file mode 100644 index 0000000..64cde72 --- /dev/null +++ b/test/test_issue_comment_on_failure.py @@ -0,0 +1,83 @@ +import pytest +from unittest.mock import MagicMock, patch +from pathlib import Path + +from aider_gitea import push_changes + + +class TestIssueCommentOnFailure: + def setup_method(self): + self.cwd = Path('/tmp/test-repo') + self.branch_name = 'issue-123-test-branch' + self.issue_number = '123' + self.issue_title = 'Test Issue' + self.base_branch = 'main' + self.gitea_client = MagicMock() + self.owner = 'test-owner' + self.repo = 'test-repo' + + @patch('aider_gitea.has_commits_on_branch', return_value=True) + @patch('aider_gitea.get_commit_messages', return_value=['Test commit']) + @patch('aider_gitea.run_cmd') + def test_comment_on_push_failure(self, mock_run_cmd, mock_get_commit_messages, mock_has_commits): + # Setup run_cmd to fail on git push + mock_run_cmd.return_value = False + + # Call push_changes + result = push_changes( + self.cwd, + self.branch_name, + self.issue_number, + self.issue_title, + self.base_branch, + self.gitea_client, + self.owner, + self.repo + ) + + # Verify result is False + assert result is False + + # Verify create_issue_comment was called with appropriate message + self.gitea_client.create_issue_comment.assert_called_once() + args, _ = self.gitea_client.create_issue_comment.call_args + assert args[0] == self.owner + assert args[1] == self.repo + assert args[2] == self.issue_number + assert "Failed to push branch" in args[3] + assert "❌ **Automated Solution Failed**" in args[3] + + @patch('aider_gitea.has_commits_on_branch', return_value=True) + @patch('aider_gitea.get_commit_messages', return_value=['Test commit']) + @patch('aider_gitea.run_cmd') + def test_comment_on_pr_creation_failure(self, mock_run_cmd, mock_get_commit_messages, mock_has_commits): + # Setup run_cmd to succeed on git push + mock_run_cmd.return_value = True + + # Setup create_pull_request to fail + self.gitea_client.create_pull_request.side_effect = Exception("PR creation failed") + + # Call push_changes + result = push_changes( + self.cwd, + self.branch_name, + self.issue_number, + self.issue_title, + self.base_branch, + self.gitea_client, + self.owner, + self.repo + ) + + # Verify result is False + assert result is False + + # Verify create_issue_comment was called with appropriate message + self.gitea_client.create_issue_comment.assert_called_once() + args, _ = self.gitea_client.create_issue_comment.call_args + assert args[0] == self.owner + assert args[1] == self.repo + assert args[2] == self.issue_number + assert "Failed to create pull request" in args[3] + assert "⚠️ **Partial Automation Success**" in args[3] + assert self.branch_name in args[3]