From e14beacc19fff26fd66037f0e4579517727d4c85 Mon Sep 17 00:00:00 2001 From: Kris Rane Date: Thu, 7 Aug 2025 17:56:46 +0800 Subject: [PATCH 1/7] feat: enhance BitbucketServerProvider authentication with username and password fallback --- .../git_providers/bitbucket_server_provider.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/pr_agent/git_providers/bitbucket_server_provider.py b/pr_agent/git_providers/bitbucket_server_provider.py index 43cdad7c..ab249b57 100644 --- a/pr_agent/git_providers/bitbucket_server_provider.py +++ b/pr_agent/git_providers/bitbucket_server_provider.py @@ -38,10 +38,22 @@ class BitbucketServerProvider(GitProvider): self.diff_files = None self.bitbucket_pull_request_api_url = pr_url self.bearer_token = get_settings().get("BITBUCKET_SERVER.BEARER_TOKEN", None) + #get username and password from settings + self.username = get_settings().get("BITBUCKET_SERVER.USERNAME", None) + self.password = get_settings().get("BITBUCKET_SERVER.PASSWORD", None) self.bitbucket_server_url = self._parse_bitbucket_server(url=pr_url) - self.bitbucket_client = bitbucket_client or Bitbucket(url=self.bitbucket_server_url, - token=get_settings().get("BITBUCKET_SERVER.BEARER_TOKEN", - None)) + #if bearer token is provided, use it to authenticate, otherwise use username and password + if self.bearer_token: + self.bitbucket_client = bitbucket_client or Bitbucket( + url=self.bitbucket_server_url, + token=self.bearer_token + ) + else: + self.bitbucket_client = bitbucket_client or Bitbucket( + url=self.bitbucket_server_url, + username=self.username, + password=self.password + ) try: self.bitbucket_api_version = parse_version(self.bitbucket_client.get("rest/api/1.0/application-properties").get('version')) except Exception: From af803ce473baf0a915a31a30876451a6ab4408c8 Mon Sep 17 00:00:00 2001 From: Boston008 Date: Sun, 10 Aug 2025 15:09:13 +0800 Subject: [PATCH 2/7] Update bitbucket_server_provider.py implement improve suggestion --- .../bitbucket_server_provider.py | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/pr_agent/git_providers/bitbucket_server_provider.py b/pr_agent/git_providers/bitbucket_server_provider.py index ab249b57..c706a563 100644 --- a/pr_agent/git_providers/bitbucket_server_provider.py +++ b/pr_agent/git_providers/bitbucket_server_provider.py @@ -38,22 +38,31 @@ class BitbucketServerProvider(GitProvider): self.diff_files = None self.bitbucket_pull_request_api_url = pr_url self.bearer_token = get_settings().get("BITBUCKET_SERVER.BEARER_TOKEN", None) - #get username and password from settings + #Get username and password from settings self.username = get_settings().get("BITBUCKET_SERVER.USERNAME", None) self.password = get_settings().get("BITBUCKET_SERVER.PASSWORD", None) + if not self.bitbucket_server_url: + raise ValueError("Invalid or missing Bitbucket Server URL parsed from PR URL.") self.bitbucket_server_url = self._parse_bitbucket_server(url=pr_url) - #if bearer token is provided, use it to authenticate, otherwise use username and password - if self.bearer_token: - self.bitbucket_client = bitbucket_client or Bitbucket( - url=self.bitbucket_server_url, - token=self.bearer_token - ) - else: - self.bitbucket_client = bitbucket_client or Bitbucket( - url=self.bitbucket_server_url, - username=self.username, - password=self.password - ) + #If bearer token is provided, use it to authenticate, otherwise use username and password + try: + if self.bearer_token: + self.bitbucket_client = bitbucket_client or Bitbucket( + url=self.bitbucket_server_url, + token=self.bearer_token + ) + else: + if not self.username or not self.password: + raise ValueError("Bitbucket authentication requires either 'BITBUCKET_SERVER.BEARER_TOKEN' or both 'BITBUCKET_SERVER.USERNAME' and 'BITBUCKET_SERVER.PASSWORD'.") + + self.bitbucket_client = bitbucket_client or Bitbucket( + url=self.bitbucket_server_url, + username=self.username, + password=self.password + ) + except Exception as e: + get_logger().error(f"Failed to initialize Bitbucket client for {self.bitbucket_server_url}: {e}") + raise try: self.bitbucket_api_version = parse_version(self.bitbucket_client.get("rest/api/1.0/application-properties").get('version')) except Exception: From 4a6a55ca7c658ff111644bc1cb8bc76b4af34d5d Mon Sep 17 00:00:00 2001 From: Boston008 Date: Mon, 11 Aug 2025 09:46:26 +0800 Subject: [PATCH 3/7] Update pr_agent/git_providers/bitbucket_server_provider.py Co-authored-by: qodo-merge-for-open-source[bot] <189517486+qodo-merge-for-open-source[bot]@users.noreply.github.com> --- pr_agent/git_providers/bitbucket_server_provider.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pr_agent/git_providers/bitbucket_server_provider.py b/pr_agent/git_providers/bitbucket_server_provider.py index c706a563..93d104e1 100644 --- a/pr_agent/git_providers/bitbucket_server_provider.py +++ b/pr_agent/git_providers/bitbucket_server_provider.py @@ -38,7 +38,7 @@ class BitbucketServerProvider(GitProvider): self.diff_files = None self.bitbucket_pull_request_api_url = pr_url self.bearer_token = get_settings().get("BITBUCKET_SERVER.BEARER_TOKEN", None) - #Get username and password from settings + # Get username and password from settings self.username = get_settings().get("BITBUCKET_SERVER.USERNAME", None) self.password = get_settings().get("BITBUCKET_SERVER.PASSWORD", None) if not self.bitbucket_server_url: From 34b562db22b5f82546131e4184fc0a38eeb65da8 Mon Sep 17 00:00:00 2001 From: Boston008 Date: Mon, 11 Aug 2025 09:46:37 +0800 Subject: [PATCH 4/7] Update pr_agent/git_providers/bitbucket_server_provider.py Co-authored-by: qodo-merge-for-open-source[bot] <189517486+qodo-merge-for-open-source[bot]@users.noreply.github.com> --- pr_agent/git_providers/bitbucket_server_provider.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pr_agent/git_providers/bitbucket_server_provider.py b/pr_agent/git_providers/bitbucket_server_provider.py index 93d104e1..21c673d7 100644 --- a/pr_agent/git_providers/bitbucket_server_provider.py +++ b/pr_agent/git_providers/bitbucket_server_provider.py @@ -44,7 +44,7 @@ class BitbucketServerProvider(GitProvider): if not self.bitbucket_server_url: raise ValueError("Invalid or missing Bitbucket Server URL parsed from PR URL.") self.bitbucket_server_url = self._parse_bitbucket_server(url=pr_url) - #If bearer token is provided, use it to authenticate, otherwise use username and password + # If bearer token is provided, use it to authenticate, otherwise use username and password try: if self.bearer_token: self.bitbucket_client = bitbucket_client or Bitbucket( From bcfd2b3d6d7d921b1402ee3a19e1320e60f398a1 Mon Sep 17 00:00:00 2001 From: Boston008 Date: Mon, 11 Aug 2025 09:47:16 +0800 Subject: [PATCH 5/7] Update pr_agent/git_providers/bitbucket_server_provider.py Co-authored-by: qodo-merge-for-open-source[bot] <189517486+qodo-merge-for-open-source[bot]@users.noreply.github.com> --- pr_agent/git_providers/bitbucket_server_provider.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pr_agent/git_providers/bitbucket_server_provider.py b/pr_agent/git_providers/bitbucket_server_provider.py index 21c673d7..cc798bce 100644 --- a/pr_agent/git_providers/bitbucket_server_provider.py +++ b/pr_agent/git_providers/bitbucket_server_provider.py @@ -41,9 +41,9 @@ class BitbucketServerProvider(GitProvider): # Get username and password from settings self.username = get_settings().get("BITBUCKET_SERVER.USERNAME", None) self.password = get_settings().get("BITBUCKET_SERVER.PASSWORD", None) + self.bitbucket_server_url = self._parse_bitbucket_server(url=pr_url) if not self.bitbucket_server_url: raise ValueError("Invalid or missing Bitbucket Server URL parsed from PR URL.") - self.bitbucket_server_url = self._parse_bitbucket_server(url=pr_url) # If bearer token is provided, use it to authenticate, otherwise use username and password try: if self.bearer_token: From 01f16f57ca97e7168b2ea0146cd5dbfe5abe2f07 Mon Sep 17 00:00:00 2001 From: Boston008 Date: Mon, 11 Aug 2025 12:18:05 +0800 Subject: [PATCH 6/7] Update bitbucket_server_provider.py --- pr_agent/git_providers/bitbucket_server_provider.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pr_agent/git_providers/bitbucket_server_provider.py b/pr_agent/git_providers/bitbucket_server_provider.py index cc798bce..c91c4611 100644 --- a/pr_agent/git_providers/bitbucket_server_provider.py +++ b/pr_agent/git_providers/bitbucket_server_provider.py @@ -39,8 +39,8 @@ class BitbucketServerProvider(GitProvider): self.bitbucket_pull_request_api_url = pr_url self.bearer_token = get_settings().get("BITBUCKET_SERVER.BEARER_TOKEN", None) # Get username and password from settings - self.username = get_settings().get("BITBUCKET_SERVER.USERNAME", None) - self.password = get_settings().get("BITBUCKET_SERVER.PASSWORD", None) + username = get_settings().get("BITBUCKET_SERVER.USERNAME", None) + password = get_settings().get("BITBUCKET_SERVER.PASSWORD", None) self.bitbucket_server_url = self._parse_bitbucket_server(url=pr_url) if not self.bitbucket_server_url: raise ValueError("Invalid or missing Bitbucket Server URL parsed from PR URL.") @@ -52,13 +52,13 @@ class BitbucketServerProvider(GitProvider): token=self.bearer_token ) else: - if not self.username or not self.password: + if not username or not password: raise ValueError("Bitbucket authentication requires either 'BITBUCKET_SERVER.BEARER_TOKEN' or both 'BITBUCKET_SERVER.USERNAME' and 'BITBUCKET_SERVER.PASSWORD'.") self.bitbucket_client = bitbucket_client or Bitbucket( url=self.bitbucket_server_url, - username=self.username, - password=self.password + username=username, + password=password ) except Exception as e: get_logger().error(f"Failed to initialize Bitbucket client for {self.bitbucket_server_url}: {e}") From e0a4be13976c4a405f193558c302eeaf974fd903 Mon Sep 17 00:00:00 2001 From: Boston008 Date: Wed, 13 Aug 2025 12:46:50 +0800 Subject: [PATCH 7/7] Update bitbucket_server_provider.py --- .../bitbucket_server_provider.py | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/pr_agent/git_providers/bitbucket_server_provider.py b/pr_agent/git_providers/bitbucket_server_provider.py index c91c4611..f805d0c2 100644 --- a/pr_agent/git_providers/bitbucket_server_provider.py +++ b/pr_agent/git_providers/bitbucket_server_provider.py @@ -41,28 +41,36 @@ class BitbucketServerProvider(GitProvider): # Get username and password from settings username = get_settings().get("BITBUCKET_SERVER.USERNAME", None) password = get_settings().get("BITBUCKET_SERVER.PASSWORD", None) - self.bitbucket_server_url = self._parse_bitbucket_server(url=pr_url) - if not self.bitbucket_server_url: + # If bitbucket_client is provided, try to extract the server URL from its configuration + if bitbucket_client: + self.bitbucket_client = bitbucket_client + try: + # Get the base URL from the existing client + self.bitbucket_server_url = bitbucket_client.url + except AttributeError: + # If we can't get the URL from the client, try parsing it from PR URL + self.bitbucket_server_url = self._parse_bitbucket_server(url=pr_url) if pr_url else None + else: + # Parse server URL from PR URL + self.bitbucket_server_url = self._parse_bitbucket_server(url=pr_url) if pr_url else None + + # Validate the server URL unless we have a pre-configured client + if not bitbucket_client and not self.bitbucket_server_url: raise ValueError("Invalid or missing Bitbucket Server URL parsed from PR URL.") - # If bearer token is provided, use it to authenticate, otherwise use username and password - try: + + # If no client provided, create one with the appropriate authentication + if not bitbucket_client: if self.bearer_token: - self.bitbucket_client = bitbucket_client or Bitbucket( + self.bitbucket_client = Bitbucket( url=self.bitbucket_server_url, token=self.bearer_token ) else: - if not username or not password: - raise ValueError("Bitbucket authentication requires either 'BITBUCKET_SERVER.BEARER_TOKEN' or both 'BITBUCKET_SERVER.USERNAME' and 'BITBUCKET_SERVER.PASSWORD'.") - - self.bitbucket_client = bitbucket_client or Bitbucket( + self.bitbucket_client = Bitbucket( url=self.bitbucket_server_url, username=username, password=password ) - except Exception as e: - get_logger().error(f"Failed to initialize Bitbucket client for {self.bitbucket_server_url}: {e}") - raise try: self.bitbucket_api_version = parse_version(self.bitbucket_client.get("rest/api/1.0/application-properties").get('version')) except Exception: