Skip to content

[JIRA] Add search/jql and search/approximate-count APIs support for Jira Cloud #1513

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,23 @@ And here's another example of how to get issues from Jira using JQL Query:
data = jira.jql(JQL)
print(data)

The traditional jql method is deprecated for Jira Cloud users, as Atlassian has transitioned to a nextPageToken-based pagination approach instead of startAt. Use enhanced_jql for improved performance and future compatibility.

.. code-block:: python

from atlassian import Jira

jira = Jira(
url='https://your-jira-instance.atlassian.net',
username='your-email@example.com',
password='your-api-token',
cloud=True # Ensure this is set to True for Jira Cloud
)
JQL = 'project = DEMO AND status IN ("To Do", "In Progress") ORDER BY issuekey'
# Fetch issues using the new enhanced_jql method
data = jira.enhanced_jql(JQL)
print(data)

Also, you can use the Bitbucket module e.g. for getting project list

.. code-block:: python
Expand Down
140 changes: 139 additions & 1 deletion atlassian/jira.py
Original file line number Diff line number Diff line change
Expand Up @@ -3397,6 +3397,19 @@ def jql(
:param validate_query: OPTIONAL: Whether to validate the JQL query
:return:
"""
if self.cloud:
if start==0:
return self.enhanced_jql(
jql=jql,
fields=fields,
limit=limit,
expand=expand,
)
else:
raise ValueError(
"The `jql` method is deprecated in Jira Cloud. Use `enhanced_jql` method instead."
)

params = {}
if start is not None:
params["startAt"] = int(start)
Expand All @@ -3415,6 +3428,64 @@ def jql(
url = self.resource_url("search")
return self.get(url, params=params)

def enhanced_jql(
self,
jql,
fields="*all",
nextPageToken=None,
limit=None,
expand=None,
):
"""
Get issues from jql search result with all related fields
:param jql:
:param fields: list of fields, for example: ['priority', 'summary', 'customfield_10007']
:param nextPageToken (Optional[str]): Token for paginated results. Default: None.
:param limit: OPTIONAL: The limit of the number of issues to return, this may be restricted by
fixed system limits. Default by built-in method: 50
:param expand: OPTIONAL: expand the search result
:return:
"""

if not self.cloud:
raise ValueError("``enhanced_jql`` method is only available for Jira Cloud platform")

params = {}
if nextPageToken is not None:
params["nextPageToken"] = str(nextPageToken)
if limit is not None:
params["maxResults"] = int(limit)
if fields is not None:
if isinstance(fields, (list, tuple, set)):
fields = ",".join(fields)
params["fields"] = fields
if jql is not None:
params["jql"] = jql
if expand is not None:
params["expand"] = expand

url = self.resource_url("search/jql")
return self.get(url, params=params)

def approximate_issue_count(
self,
jql,
):
"""
Get an approximate count of issues matching a JQL search string.

:param jql: The JQL search string.
:return: The issue count.
"""

if not self.cloud:
raise ValueError("``approximate_issue_count`` method is only available for Jira Cloud platform")

data = {"jql": jql}

url = self.resource_url("search/approximate-count")
return self.post(url, data)

def jql_get_list_of_tickets(
self,
jql,
Expand All @@ -3435,6 +3506,19 @@ def jql_get_list_of_tickets(
:param validate_query: Whether to validate the JQL query
:return:
"""
if self.cloud:
if start==0:
return self.enhanced_jql_get_list_of_tickets(
jql=jql,
fields=fields,
limit=limit,
expand=expand,
)
else:
raise ValueError(
"The `jql_get_list_of_tickets` method is deprecated in Jira Cloud. Use `enhanced_jql_get_list_of_tickets` method instead."
)

params = {}
if limit is not None:
params["maxResults"] = int(limit)
Expand All @@ -3456,7 +3540,7 @@ def jql_get_list_of_tickets(
response = self.get(url, params=params)
if not response:
break

issues = response["issues"]
results.extend(issues)
total = int(response["total"])
Expand All @@ -3465,7 +3549,61 @@ def jql_get_list_of_tickets(
if limit is not None or total <= len(response["issues"]) + start:
break
start += len(issues)
return results

def enhanced_jql_get_list_of_tickets(
self,
jql,
fields="*all",
limit=None,
expand=None,
):
"""
Get issues from JQL search result with all related fields using nextPageToken pagination.

Applicable only for Jira Cloud.

:param jql: The JQL search string.
:param fields: List of fields, for example: ['priority', 'summary', 'customfield_10007']
:param limit: OPTIONAL: The limit of the number of issues to return, this may be restricted by
fixed system limits. Default by built-in method: 50
:param expand: OPTIONAL: Expand the search result.
:return: List of issues.
"""

if not self.cloud:
raise ValueError("``enhanced_jql_get_list_of_tickets`` is only available for Jira Cloud.")

params = {}
if limit is not None:
params["maxResults"] = int(limit)
if fields is not None:
if isinstance(fields, (list, tuple, set)):
fields = ",".join(fields)
params["fields"] = fields
if jql is not None:
params["jql"] = jql
if expand is not None:
params["expand"] = expand

url = self.resource_url("search/jql")
results = []
nextPageToken = None

while True:
if nextPageToken is not None:
params["nextPageToken"] = nextPageToken

response = self.get(url, params=params)
if not response:
break

issues = response["issues"]
results.extend(issues)

nextPageToken = response.get("nextPageToken")
if not nextPageToken or (limit is not None and len(results) >= limit):
break
return results

def csv(self, jql, limit=1000, all_fields=True, start=None, delimiter=None):
Expand Down
35 changes: 35 additions & 0 deletions examples/jira/jira_search_issues_cloud.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# coding=utf-8
"""
Example: Using enhanced JQL search methods in Jira Cloud.

This script demonstrates:
1. Fetching issues using `enhanced_jql` (nextPageToken-based pagination).
2. Getting an approximate issue count with `approximate_issue_count`.
3. Fetching issues using `enhanced_jql_get_list_of_tickets` (legacy startAt pagination for Data Center users).

⚠️ Note: `enhanced_jql` is recommended for Jira Cloud users as it aligns with Atlassian's new search API.
"""

from atlassian import Jira

# Initialize Jira Cloud instance
jira_cloud = Jira(
cloud=True,
url="https://your-jira-instance.atlassian.net",
username="your-email@example.com",
password="your-api-token",
)

print("========== Fetching Issues Using enhanced_jql ==========")
issues = jira_cloud.enhanced_jql("updated >= -1d ORDER BY updated DESC", limit=20, fields="*nav")
print(issues)

print("========== Getting Approximate Issue Count ==========")
issue_count = jira_cloud.approximate_issue_count("updated >= -1d ORDER BY updated DESC")
print(issue_count)

print("========== Fetching Issues Using enhanced_jql_get_list_of_tickets ==========")
issues_list = jira_cloud.enhanced_jql_get_list_of_tickets("updated >= -1d ORDER BY updated DESC", limit=300, fields="*nav")
print(issues_list)

print("========== Done ==========")
Loading