Search for Issues
Migrating to Jira Cloud? This feature is available in Cloud. |
With HAPI, we've made it easy for you to search for issues.
Running JQL queries to search for issues
With HAPI, you can easily run JQL queries.
Where the example says "do something with each issue" you can, for example, update all returned issues using the issue.update method.
Issues.search returns an Iterator. This is designed for you to iterate through the results instead of retaining many issues in memory. You should not call methods such as size() and count() on the iterator, as this will exhaust it and make any subsequent iterations return zero elements. If you require a count of the results of a JQL query, you can use Issues.count to get this first.Issues.search("project = 'ABC' AND issuetype = 'Task'").each { issue ->
// do something with `issue`
log.warn(issue.key)
}Updating all returned issues
As mentioned above, you can update all returned issues using the issue.update method. This is particularly useful if you want to bulk update issues.
Issues.search("project = 'ABC' AND issuetype = 'Task' AND priority = Low").each { issue ->
issue.update {
setComment('This task needs looking at')
setPriority('High')
}
log.warn(issue.key)
}JQL queries and memory
We recommend that you do NOT execute queries using an unlimited PagerFilter. The returned issues are temporarily stored in memory if you execute a query without paging.
With HAPI, issues are fetched in batches from the Lucene index (transparent to the script), ensuring that memory usage is constant, and that you don't cause an OutOfMemoryException.
Limiting list size for JQL queries
If you really need a List of issues, limit the size, as shown below.
Issues.search('project = ABC').take(1_000).toList()One thousand issues in a list are acceptable, tens of thousands might be acceptable, but millions are not.
If you need a count of issues, use count. This provides better performance than executing a query and iterating through them all just to count them:
def issueCount = Issues.count('project = ABC')JQL queries and security
Permissions are respected, so will return the same set of issues as you would see if you executed the query in Jira.
If you want to return issues regardless of whether the current user can see them, use the methods Jql.queryOverrideSecurity and Jql.countOverrideSecurity. For example, if we take the examples from the section above, you would enter the following into the script console:
Issues.searchOverrideSecurity('project = ABC').take(1_000).toList()or
def issueCount = Issues.countOverrideSecurity('project = ABC')Matching against an issue
Often it can be handy to check whether an issue matches a query because it's easier to test the issue's attributes with JQL, or with a user-supplied JQL string.
def issue = Issues.getByKey('ABC-1')
issue.matches('project = ABC') // trueThe permissions of the current user are respected. If you want to test whether the issue matches the query regardless of permissions, use matchesOverrideSecurity instead of matches.
Advanced HAPI JQL usage
You may want to filter the list of issues further because you want a condition you cannot express in JQL.
Issues.search('project = ABC').findAll { issue ->
issue.assignee?.name == 'admin'
}.each { issue ->
// ...
}Limiting the number of issues searched
Groovy Development Kit methods such as findAll collect as many issues as they can, which isn't ideal. If you have a very large instance for tasks such as the one above or advanced data processing pipelines, you can use the java Streams API. The stream() method is available on the search result for convenience.
import java.util.stream.Collectors
Issues.search('project = ABC')
.stream()
.filter { issue -> issue.assignee?.name == 'admin' }
.limit(10)
.collect(Collectors.toList())The above example stops fetching issues and checking the condition, once ten issues have been found. Whereas similar code written with GDK methods processes all issues matching the JQL query, collects all matching the filter, and then takes ten.