diff --git a/jbi/jira/client.py b/jbi/jira/client.py index 8de7efef..607c11b8 100644 --- a/jbi/jira/client.py +++ b/jbi/jira/client.py @@ -1,5 +1,5 @@ import logging -from typing import Collection, Iterable, Optional +from typing import Any, Collection, Iterable, Optional, Union import requests from atlassian import Jira @@ -84,7 +84,7 @@ def paginated_projects( expand=None, url=None, keys: Optional[Collection[str]] = None, - ): + ) -> dict: """Returns a paginated list of projects visible to the user. https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-projects/#api-rest-api-2-project-search-get @@ -97,20 +97,23 @@ def paginated_projects( "``projects_from_cloud`` method is only available for Jira Cloud platform" ) - params = [] + params_dict: dict[str, Any] = {} if keys is not None: if len(keys) > 50: raise ValueError("Up to 50 project keys can be provided.") - params = [("keys", key) for key in keys] + params_dict["keys"] = list(keys) if included_archived: - params.append(("includeArchived", included_archived)) + params_dict["includeArchived"] = included_archived if expand: - params.append(("expand", expand)) + params_dict["expand"] = expand page_url = url or self.resource_url("project/search") is_url_absolute = bool(page_url.lower().startswith("http")) - return self.get(page_url, params=params, absolute=is_url_absolute) + projects: Union[dict, None] = self.get( + page_url, params=params_dict, absolute=is_url_absolute + ) + return projects if projects else {"values": []} @instrumented_method def permitted_projects(self, permissions: Optional[Iterable] = None) -> list[dict]: @@ -125,5 +128,5 @@ def permitted_projects(self, permissions: Optional[Iterable] = None) -> list[dic "/rest/api/2/permissions/project", json={"permissions": list(permissions)}, ) - projects: list[dict] = response["projects"] + projects: list[dict] = response["projects"] if response else [] return projects diff --git a/jbi/jira/service.py b/jbi/jira/service.py index be133d68..6654cd93 100644 --- a/jbi/jira/service.py +++ b/jbi/jira/service.py @@ -522,7 +522,7 @@ def check_jira_all_project_issue_types_exist(self, actions): try: paginated_project_response = self.client.paginated_projects( - expand="issueTypes", keys=actions.configured_jira_projects_keys + expand="issueTypes", keys=sorted(actions.configured_jira_projects_keys) ) except requests.RequestException: return [ diff --git a/poetry.lock b/poetry.lock index 3465a442..ea6f6b08 100644 --- a/poetry.lock +++ b/poetry.lock @@ -50,14 +50,14 @@ tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] [[package]] name = "atlassian-python-api" -version = "3.41.21" +version = "4.0.3" description = "Python Atlassian REST API Wrapper" optional = false python-versions = "*" groups = ["main"] files = [ - {file = "atlassian_python_api-3.41.21-py3-none-any.whl", hash = "sha256:6397bfa08d19acf08a766d3db5dd782348e8a3efca49cbf4ada870290a7fcf07"}, - {file = "atlassian_python_api-3.41.21.tar.gz", hash = "sha256:30117504ebdcbe229c6a15f7a6b89076e7f20e5feeb425fbce2b4b0b18b0e639"}, + {file = "atlassian_python_api-4.0.3-py3-none-any.whl", hash = "sha256:23d9f0d33af260bbe7cec7edde125ce40b370183da7bf2f1c012ff5cfe721fa0"}, + {file = "atlassian_python_api-4.0.3.tar.gz", hash = "sha256:c5347e15c5a0a2ce987767c3428d112680fb5c4228f2f309009d9b01b5bea22e"}, ] [package.dependencies] @@ -68,6 +68,7 @@ oauthlib = "*" requests = "*" requests_oauthlib = "*" six = "*" +typing-extensions = "*" [package.extras] kerberos = ["requests-kerberos"] @@ -2198,4 +2199,4 @@ dev = ["doc8", "flake8", "flake8-import-order", "rstcheck[sphinx]", "sphinx"] [metadata] lock-version = "2.1" python-versions = ">=3.12, <3.14" -content-hash = "a51972eac1bbb26bac17804883becf799f7a234a0a28c7ff9734d240da66befc" +content-hash = "fe6ffed9c9abdcd97e661283ce95984bc5f14f4e445244a9fb0fc0c12b82e073" diff --git a/pyproject.toml b/pyproject.toml index 1fb47e6c..5aa9cb06 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ python = ">=3.12, <3.14" fastapi = "^0.115.12" pydantic = {version = "^2.11.3", extras = ["email"]} uvicorn = {extras = ["standard"], version = "^0.34.2"} -atlassian-python-api = "^3.41.21" +atlassian-python-api = "^4.0.3" dockerflow = {extras = ["fastapi"], version = "2024.4.2"} Jinja2 = "^3.1.6" sentry-sdk = {extras = ["fastapi"], version = "^2.27.0"} diff --git a/tests/unit/jira/test_client.py b/tests/unit/jira/test_client.py index 35bfb6a0..be3cbd22 100644 --- a/tests/unit/jira/test_client.py +++ b/tests/unit/jira/test_client.py @@ -86,7 +86,7 @@ def test_paginated_projects_with_keys(settings, jira_client, mocked_responses): responses.GET, url, status=200, - match=[responses.matchers.query_string_matcher("keys=ABC&keys=DEF")], + match=[responses.matchers.query_string_matcher("keys=['ABC', 'DEF']")], json=mocked_response_data, ) resp = jira_client.paginated_projects(keys=["ABC", "DEF"]) diff --git a/tests/unit/jira/test_service.py b/tests/unit/jira/test_service.py index 5800de0b..19ede6fe 100644 --- a/tests/unit/jira/test_service.py +++ b/tests/unit/jira/test_service.py @@ -422,8 +422,8 @@ def test_all_project_issue_types_exist( status=200, match=[ responses.matchers.query_string_matcher( - "keys=ABC&keys=DEF&expand=issueTypes" - ) + "keys=['ABC', 'DEF']&expand=issueTypes" + ), ], json={"values": project_data}, )