Skip to content

feat(jira): search issues by JQL from both providers - #6758

Open
purisev wants to merge 3 commits into
keephq:mainfrom
purisev:feat/jira-jql
Open

feat(jira): search issues by JQL from both providers#6758
purisev wants to merge 3 commits into
keephq:mainfrom
purisev:feat/jira-jql

Conversation

@purisev

@purisev purisev commented Sep 3, 2026

Copy link
Copy Markdown

Problem

See #6753. _query can fetch one issue by key or count a board, and it drops the
issues it fetched. A workflow cannot ask a question narrower than "how many
issues does this board hold".

Fix

Two commits, one per provider. _query takes jql, max_results and fields
and returns {"total": ..., "jql": ..., "issues": [...]}. The ticket_id and
board_id paths are untouched.

On Server and Data Center one GET to /rest/api/2/search carries jql,
maxResults and the optional fields, and the response holds the total and the
page together. issues is always a list, empty when max_results is zero, so a
foreach over it is a no-op rather than a missing key.

Cloud needs two endpoints and tries to spend one request. search/jql reports no
total, so the count comes from search/approximate-count; the search is skipped
when max_results is zero, and the count is skipped when the page Jira returned
is the whole answer. A page counts as whole when it carries no nextPageToken
and is shorter than max_results, so a deployment that omits the token cannot
pass a capped number off as the total.

In both providers max_results goes through int(), since a workflow hands over
strings, and a value that is not a number raises a ProviderException naming it.
fields takes a list or a comma separated string.

Tests

tests/test_jira_provider.py grows to 24 tests, all passing: the count-only
default, a page of issues, fields reaching the request, a non-numeric
max_results, a failed request on either endpoint, and the ticket_id path
behaving as before. The Cloud tests also cover the request the provider does not
send, both for a whole page and for one filled to max_results.

Docs

Two example workflows, examples/workflows/jira_cloud_stale_issues.yml and
examples/workflows/jira_on_prem_stale_issues.yml, and the snippets regenerated
from the new docstrings. Both examples post their results to Slack, which is why
the Slack snippet's example list picks them up as well.

Note on the other Jira PRs

#6755, #6756 and #6757 cover the other three reports on these providers. This PR
shares only tests/test_jira_provider.py with them, where the blocks are added
side by side.

Fixes #6753

_query could only fetch one issue by key or count every issue on a board.
Neither filters by status, age or issue type, so a workflow had no way to find
the issues matching a condition, let alone act on them.

With jql set the provider calls /rest/api/2/search and returns the total
alongside the issues. max_results says how many issues to carry back and
defaults to zero, which asks Jira for the count alone; issues is an empty list
even then, rather than a missing key, so a foreach over it is a no-op instead
of a failure. fields limits what each issue carries, as a comma separated
string or a list, because otherwise every issue arrives with all of its fields
and a page of them is megabytes of workflow context. A max_results that is not
a number is refused before the request. ticket_id and board_id callers are
unchanged.

The example workflow searches for issues left open past a threshold and posts
one Slack message per issue. The generated provider snippets follow the new
arguments and the new example.

Signed-off-by: Iurii Purisev <92510590+purisev@users.noreply.github.com>
The on-prem provider takes a jql, the cloud one could still only fetch one
ticket or count a whole board, so the same workflow could not be pointed at
Jira Cloud.

Cloud cannot make the on-prem request. /rest/api/2/search is deprecated there
and is being removed, and the search/jql that replaces it reports no total at
all, so the issues come from search/jql and the count, when it is needed, from
search/approximate-count. A page Jira did not have to truncate is the whole
answer and already carries the total, so the common query costs one request and
reports an exact total rather than an approximate one; only a truncated page,
or a query that asks for no issues at all, goes on to the count endpoint. A
page filled to max_results counts as truncated, so a capped number is never
reported as the total.

The result keeps the shape the on-prem provider returns, total, jql and issues,
so moving a workflow between the two is a change of provider type.

Signed-off-by: Iurii Purisev <92510590+purisev@users.noreply.github.com>

@shahargl shahargl left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Cloud JQL approach is sound (search/jql + approximate-count, skip the extra request when the page is complete). Please fix the on-prem crash before merge.

Blocking: on-prem JQL search uses self.authentication_config.verify, but JiraonpremProviderAuthConfig has no verify field. That is an AttributeError on every JQL query. The new test asserts verify is False and would fail the same way. Use verify=False like the rest of this provider, or add a real verify field to the auth config.

Also: Cloud /search/jql defaults to fields=id, not all fields. The docstring and example comment say an empty fields returns every field — that is true for on-prem /rest/api/2/search, not Cloud. When fields is empty on Cloud, send *all (or *navigable) if that is the intended behavior.

CI for this fork PR is still waiting for workflow approval, so the new tests have not run yet.

response = requests.get(
request_url,
headers=self.__get_auth_header(),
verify=self.authentication_config.verify,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking: JiraonpremProviderAuthConfig has no verify field (host, personal_access_token, ticket_creation_url only). This raises AttributeError on every JQL query, before the request is sent.

The new test also asserts verify is False, so it would fail here too.

Use verify=False like the other requests in this provider, or add a real verify field to the auth config.

if max_results:
query_params = {"jql": jql, "maxResults": max_results}
if fields:
query_params["fields"] = fields

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cloud /search/jql defaults to fields=id when this param is omitted, not all fields. The docstring and the stale-issue example comment say the opposite.

When fields is empty, send *all (or *navigable) if you want the documented behavior. The example workflows already pass an explicit field list, so those paths are fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[➕ Feature]: Query Jira issues by JQL from both Jira providers

2 participants