diff --git a/lib/sniper/webhook.ex b/lib/sniper/webhook.ex index ab7e2ce..7e32958 100644 --- a/lib/sniper/webhook.ex +++ b/lib/sniper/webhook.ex @@ -106,10 +106,14 @@ defmodule Sniper.Webhook do "ping" -> user = payload["comment"]["user"]["login"] - Task.start(fn -> Sniper.send_message(%{type: "comment", payload: pr, body: "@#{user} pong"}) end) + + Task.start(fn -> + Sniper.send_message(%{type: "comment", payload: pr, body: "@#{user} pong"}) + end) "help" -> user = payload["comment"]["user"]["login"] + help = """ @#{user} Here are the available commands: @@ -119,6 +123,7 @@ defmodule Sniper.Webhook do | `@snipercodeai ping` | Check if the bot is alive | | `@snipercodeai help` | Show this message | """ + Task.start(fn -> Sniper.send_message(%{type: "comment", payload: pr, body: help}) end) _ -> diff --git a/pythonbridge/ast/ast_manager.py b/pythonbridge/ast/ast_manager.py index d7a775f..eebdce3 100644 --- a/pythonbridge/ast/ast_manager.py +++ b/pythonbridge/ast/ast_manager.py @@ -9,7 +9,7 @@ # parser = Parser(PY_LANGUAGE) -class AST_manager: +class ASTManager: """ Manages Abstract Syntax Tree (AST) parsing and relationship extraction for Python files. diff --git a/pythonbridge/gh/client.py b/pythonbridge/gh/client.py index 020d7e0..f7bc999 100644 --- a/pythonbridge/gh/client.py +++ b/pythonbridge/gh/client.py @@ -1,6 +1,6 @@ from __future__ import annotations # issues with type hints -from github import Github, PaginatedList, File +from github import Github, PaginatedList, File, Repository from pythonbridge.gh.auth import get_installation_token @@ -12,14 +12,9 @@ def create_reaction(payload: dict, reaction_type: str = "eyes") -> None: Expected keys: "comment_id", "repository.full_name", "installation.id" reaction_type: The reaction to add (default "eyes"). """ - repo_full_name = payload.get("repository").get("full_name") - installation_id = payload.get("installation").get("id") comment_id = payload.get("comment_id") - installation_token = get_installation_token(installation_id) - pr_number = payload.get("number") - github_client = Github(installation_token) - repo = github_client.get_repo(repo_full_name) + repo = _get_repo(payload) comment = repo.get_issue(pr_number).get_comment(comment_id) comment.create_reaction(reaction_type) @@ -34,15 +29,8 @@ def get_diff(payload: dict) -> PaginatedList[File]: Returns: PaginatedList of File objects representing changed files in the PR. """ - # Get installation token pr_number = payload.get("number") - repo_full_name = payload.get("repository").get("full_name") - installation_id = payload.get("installation").get("id") - installation_token = get_installation_token(installation_id) - - # Create Github client and get changed files from PR - github_client = Github(installation_token) - repo = github_client.get_repo(repo_full_name) + repo = _get_repo(payload) pr = repo.get_pull(pr_number) files = pr.get_files() @@ -61,12 +49,7 @@ def post_review(payload: dict, reviews: list[dict]) -> None: reviews: List of review dicts with keys "filename" and "review". """ pr_number = payload.get("number") - repo_full_name = payload.get("repository").get("full_name") - installation_id = payload.get("installation").get("id") - installation_token = get_installation_token(installation_id) - - github_client = Github(installation_token) - repo = github_client.get_repo(repo_full_name) + repo = _get_repo(payload) pr = repo.get_pull(pr_number) body = "" @@ -87,11 +70,24 @@ def post_comment(payload: dict, body: str) -> None: body: The comment body to post. """ pr_number = payload.get("number") + repo = _get_repo(payload) + pr = repo.get_pull(pr_number) + pr.create_issue_comment(body) + + +def _get_repo(payload: dict) -> Repository: + """Retrieves the GitHub repository linked to the payload + + Args: + payload (dict): GitHub webhook payload containing PR details. + Expected keys: "number", "repository.full_name", "installation.id" + + Returns: + Repository: The Repository object representing the GitHub repo + """ repo_full_name = payload.get("repository").get("full_name") installation_id = payload.get("installation").get("id") installation_token = get_installation_token(installation_id) - github_client = Github(installation_token) - repo = github_client.get_repo(repo_full_name) - pr = repo.get_pull(pr_number) - pr.create_issue_comment(body) + + return github_client.get_repo(repo_full_name) diff --git a/pythonbridge/tests/core/test_review.py b/pythonbridge/tests/core/test_review.py index 1e0af12..3e8e6b3 100644 --- a/pythonbridge/tests/core/test_review.py +++ b/pythonbridge/tests/core/test_review.py @@ -14,7 +14,12 @@ class TestReview(unittest.TestCase): @patch("pythonbridge.core.review.GraphBuilder") @patch("pythonbridge.core.review.post_review") def test_review_pr_reviews_files( - self, mock_post_review, mock_graph_builder, mock_get_diff, mock_create_reaction, mock_load_env + self, + mock_post_review, + mock_graph_builder, + mock_get_diff, + mock_create_reaction, + mock_load_env, ): # https://docs.github.com/en/rest/pulls/pulls#list-pull-requests-files mock_file = Mock() @@ -52,7 +57,12 @@ def test_review_pr_reviews_files( @patch("pythonbridge.core.review.GraphBuilder") @patch("pythonbridge.core.review.post_review") def test_review_pr_skips_files_without_patch( - self, mock_post_review, mock_graph_builder, mock_get_diff, mock_create_reaction, mock_load_env + self, + mock_post_review, + mock_graph_builder, + mock_get_diff, + mock_create_reaction, + mock_load_env, ): # Deleted files have no patch (no diff to review) mock_file = Mock()