From 68f78e1a30b492fc73ada3e4832d3b155d7fb9be Mon Sep 17 00:00:00 2001 From: Alessio <148966056+alessio-locatelli@users.noreply.github.com> Date: Wed, 18 Jun 2025 10:51:19 +0300 Subject: [PATCH 1/5] fix: do not fail the CLI when GitLab API return 5xx code --- pr_agent/agent/pr_agent.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/pr_agent/agent/pr_agent.py b/pr_agent/agent/pr_agent.py index 0a42a50d..bfe924d6 100644 --- a/pr_agent/agent/pr_agent.py +++ b/pr_agent/agent/pr_agent.py @@ -1,6 +1,9 @@ import shlex from functools import partial +import gitlab +from starlette.status import HTTP_500_INTERNAL_SERVER_ERROR, HTTP_503_SERVICE_UNAVAILABLE + from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler from pr_agent.algo.ai_handlers.litellm_ai_handler import LiteLLMAIHandler from pr_agent.algo.cli_args import CliArgs @@ -113,7 +116,19 @@ class PRAgent: if notify: notify() - await command2class[action](pr_url, ai_handler=self.ai_handler, args=args).run() + try: + await command2class[action](pr_url, ai_handler=self.ai_handler, args=args).run() + except gitlab.GitlabError as gitlab_error: + # For GitLab 5xx codes see: https://docs.gitlab.com/api/rest/troubleshooting/#status-codes + if gitlab_error.response_code in {HTTP_500_INTERNAL_SERVER_ERROR, HTTP_503_SERVICE_UNAVAILABLE}: + # The problem is likely temporary and not on our side; therefore, do not fail the application. + get_logger().error( + f"Failed to process the command due to a problem on the GitLab API side: {gitlab_error!r}\n" + + "Check https://status.gitlab.com and try again later." + ) + return False + raise + else: return False return True From 1a003fe4d3798ee2f1f9fd2a2bba6cf437862f6d Mon Sep 17 00:00:00 2001 From: Alessio <148966056+alessio-locatelli@users.noreply.github.com> Date: Thu, 19 Jun 2025 09:31:06 +0300 Subject: [PATCH 2/5] fix: wrap `_handle_request` to handle 5xx responses --- pr_agent/agent/pr_agent.py | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/pr_agent/agent/pr_agent.py b/pr_agent/agent/pr_agent.py index bfe924d6..bbe76f19 100644 --- a/pr_agent/agent/pr_agent.py +++ b/pr_agent/agent/pr_agent.py @@ -54,7 +54,7 @@ class PRAgent: def __init__(self, ai_handler: partial[BaseAiHandler,] = LiteLLMAIHandler): self.ai_handler = ai_handler # will be initialized in run_action - async def handle_request(self, pr_url, request, notify=None) -> bool: + async def _handle_request(self, pr_url, request, notify=None) -> bool: # First, apply repo specific settings if exists apply_repo_settings(pr_url) @@ -116,19 +116,25 @@ class PRAgent: if notify: notify() - try: - await command2class[action](pr_url, ai_handler=self.ai_handler, args=args).run() - except gitlab.GitlabError as gitlab_error: - # For GitLab 5xx codes see: https://docs.gitlab.com/api/rest/troubleshooting/#status-codes - if gitlab_error.response_code in {HTTP_500_INTERNAL_SERVER_ERROR, HTTP_503_SERVICE_UNAVAILABLE}: - # The problem is likely temporary and not on our side; therefore, do not fail the application. - get_logger().error( - f"Failed to process the command due to a problem on the GitLab API side: {gitlab_error!r}\n" - + "Check https://status.gitlab.com and try again later." - ) - return False - raise - + await command2class[action](pr_url, ai_handler=self.ai_handler, args=args).run() else: return False return True + + async def handle_request(self, pr_url, request, notify=None) -> bool: + # We wrap the entire entry point to gracefully handle third-party + # service errors (such as the GitLab API) to cover cases when such + # errors were not handled or retried by the low-level code or upstream + # libraries. However, we avoid a bare `except` here to not silence + # critical errors on our side. + try: + return await self._handle_request(pr_url, request, notify) + except gitlab.GitlabError as gitlab_error: + # GitLab 5xx codes: https://docs.gitlab.com/api/rest/troubleshooting/#status-codes + if gitlab_error.response_code in {HTTP_500_INTERNAL_SERVER_ERROR, HTTP_503_SERVICE_UNAVAILABLE}: + get_logger().error( + f"Failed to process the command due to a problem on the GitLab API side: {gitlab_error!r}\n" + + "Check https://status.gitlab.com and try again later." + ) + return False + raise From 721ff18a6386b55d7ac6c0bfe95e750e06c2e002 Mon Sep 17 00:00:00 2001 From: Alessio <148966056+alessio-locatelli@users.noreply.github.com> Date: Sat, 21 Jun 2025 15:27:41 +0300 Subject: [PATCH 3/5] Revert "fix: wrap `_handle_request` to handle 5xx responses" This reverts commit 1a003fe4d3798ee2f1f9fd2a2bba6cf437862f6d. --- pr_agent/agent/pr_agent.py | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/pr_agent/agent/pr_agent.py b/pr_agent/agent/pr_agent.py index bbe76f19..bfe924d6 100644 --- a/pr_agent/agent/pr_agent.py +++ b/pr_agent/agent/pr_agent.py @@ -54,7 +54,7 @@ class PRAgent: def __init__(self, ai_handler: partial[BaseAiHandler,] = LiteLLMAIHandler): self.ai_handler = ai_handler # will be initialized in run_action - async def _handle_request(self, pr_url, request, notify=None) -> bool: + async def handle_request(self, pr_url, request, notify=None) -> bool: # First, apply repo specific settings if exists apply_repo_settings(pr_url) @@ -116,25 +116,19 @@ class PRAgent: if notify: notify() - await command2class[action](pr_url, ai_handler=self.ai_handler, args=args).run() + try: + await command2class[action](pr_url, ai_handler=self.ai_handler, args=args).run() + except gitlab.GitlabError as gitlab_error: + # For GitLab 5xx codes see: https://docs.gitlab.com/api/rest/troubleshooting/#status-codes + if gitlab_error.response_code in {HTTP_500_INTERNAL_SERVER_ERROR, HTTP_503_SERVICE_UNAVAILABLE}: + # The problem is likely temporary and not on our side; therefore, do not fail the application. + get_logger().error( + f"Failed to process the command due to a problem on the GitLab API side: {gitlab_error!r}\n" + + "Check https://status.gitlab.com and try again later." + ) + return False + raise + else: return False return True - - async def handle_request(self, pr_url, request, notify=None) -> bool: - # We wrap the entire entry point to gracefully handle third-party - # service errors (such as the GitLab API) to cover cases when such - # errors were not handled or retried by the low-level code or upstream - # libraries. However, we avoid a bare `except` here to not silence - # critical errors on our side. - try: - return await self._handle_request(pr_url, request, notify) - except gitlab.GitlabError as gitlab_error: - # GitLab 5xx codes: https://docs.gitlab.com/api/rest/troubleshooting/#status-codes - if gitlab_error.response_code in {HTTP_500_INTERNAL_SERVER_ERROR, HTTP_503_SERVICE_UNAVAILABLE}: - get_logger().error( - f"Failed to process the command due to a problem on the GitLab API side: {gitlab_error!r}\n" - + "Check https://status.gitlab.com and try again later." - ) - return False - raise From d00cbd4da74dd97a7e4f68ae92cfc621a16ec3cb Mon Sep 17 00:00:00 2001 From: Alessio <148966056+alessio-locatelli@users.noreply.github.com> Date: Sat, 21 Jun 2025 15:28:27 +0300 Subject: [PATCH 4/5] Revert "fix: do not fail the CLI when GitLab API return 5xx code" This reverts commit 68f78e1a30b492fc73ada3e4832d3b155d7fb9be. --- pr_agent/agent/pr_agent.py | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/pr_agent/agent/pr_agent.py b/pr_agent/agent/pr_agent.py index bfe924d6..0a42a50d 100644 --- a/pr_agent/agent/pr_agent.py +++ b/pr_agent/agent/pr_agent.py @@ -1,9 +1,6 @@ import shlex from functools import partial -import gitlab -from starlette.status import HTTP_500_INTERNAL_SERVER_ERROR, HTTP_503_SERVICE_UNAVAILABLE - from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler from pr_agent.algo.ai_handlers.litellm_ai_handler import LiteLLMAIHandler from pr_agent.algo.cli_args import CliArgs @@ -116,19 +113,7 @@ class PRAgent: if notify: notify() - try: - await command2class[action](pr_url, ai_handler=self.ai_handler, args=args).run() - except gitlab.GitlabError as gitlab_error: - # For GitLab 5xx codes see: https://docs.gitlab.com/api/rest/troubleshooting/#status-codes - if gitlab_error.response_code in {HTTP_500_INTERNAL_SERVER_ERROR, HTTP_503_SERVICE_UNAVAILABLE}: - # The problem is likely temporary and not on our side; therefore, do not fail the application. - get_logger().error( - f"Failed to process the command due to a problem on the GitLab API side: {gitlab_error!r}\n" - + "Check https://status.gitlab.com and try again later." - ) - return False - raise - + await command2class[action](pr_url, ai_handler=self.ai_handler, args=args).run() else: return False return True From bc99cf83dd0f3d1773bb0dc61f2c9793806cc04a Mon Sep 17 00:00:00 2001 From: Alessio <148966056+alessio-locatelli@users.noreply.github.com> Date: Sat, 21 Jun 2025 15:31:21 +0300 Subject: [PATCH 5/5] feat: add a bare `except` to catch all errors --- pr_agent/agent/pr_agent.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pr_agent/agent/pr_agent.py b/pr_agent/agent/pr_agent.py index 0a42a50d..1e995ffb 100644 --- a/pr_agent/agent/pr_agent.py +++ b/pr_agent/agent/pr_agent.py @@ -51,7 +51,7 @@ class PRAgent: def __init__(self, ai_handler: partial[BaseAiHandler,] = LiteLLMAIHandler): self.ai_handler = ai_handler # will be initialized in run_action - async def handle_request(self, pr_url, request, notify=None) -> bool: + async def _handle_request(self, pr_url, request, notify=None) -> bool: # First, apply repo specific settings if exists apply_repo_settings(pr_url) @@ -117,3 +117,10 @@ class PRAgent: else: return False return True + + async def handle_request(self, pr_url, request, notify=None) -> bool: + try: + return await self._handle_request(pr_url, request, notify) + except: + get_logger().exception("Failed to process the command.") + return False