New to Kestra?
Use blueprints to kickstart your first workflows.
Run a JQL search for stale Jira issues, alert Slack with the issue keys, and log the result for engineering teams.
An open Jira issue nobody has touched in weeks is easy to miss one ticket at a time; Jira's own board shows every issue looking equally current until someone sorts by updated date and scrolls. This blueprint runs the sort for you, server-side, using Jira's own query language, and reports exactly which issues have gone stale by key, not a guess from a dashboard.
This blueprint was created by Mohit Jeswani.
search_stale_issues (io.kestra.plugin.jira.issues.Get) runs jql_filter against
Jira's search API with fetchType: FETCH, so Jira's own query engine does the staleness
filtering server-side instead of this flow paging through every issue to check
client-side. Read-only; nothing in Jira is changed. allowFailure: true covers an API or
auth error without failing the flow outright.evaluate (io.kestra.plugin.core.output.OutputValues) reads the matched count directly
from the API response's own size field and collects the matched issue keys with a jq
filter.route (io.kestra.plugin.core.flow.If):summary logs the count and severity, closing the governance cycle.errors alerts Slack if the flow itself fails, for example an expired API token.issues.Get used in its
JQL search mode for a governance check, distinct from this repo's existing Jira
blueprints, which only use issues.Create to open a new issue on flow failure rather than
auditing existing ones.Jira's JQL answers one query at a time; it does not keep a schedule, compare the result
count against a tolerance you declare, or notify a Slack channel when stale issues pile up.
Kestra keeps jql_filter and max_stale_count as flow inputs, turns the query into a Slack
page naming the actual issue keys, and keeps a full execution history of every run.
jira_username.This flow calls the Jira REST API directly over HTTPS; there is no official local Jira
emulator, so search_stale_issues cannot be exercised against a local Docker container.
JIRA_API_TOKEN: the Jira API token used by search_stale_issues. In Kestra OSS, provide
it as the base64-encoded environment variable SECRET_JIRA_API_TOKEN.SLACK_WEBHOOK_URL: used by alert and the errors block. In Kestra OSS, provide it as
the base64-encoded environment variable SECRET_SLACK_WEBHOOK_URL.| Input | Default | Purpose |
|---|---|---|
jql_filter |
project = DEMO AND status NOT IN (Done, Closed) AND updated <= -14d |
JQL selecting the issues to audit |
max_stale_count |
1 |
Matched-issue count that triggers the Slack alert |
{{ outputs.search_stale_issues.rows }}: every matched issue (key, id, and the
requested fields, defaulting to summary, status, description, labels, created,
updated).{{ outputs.evaluate.values.stale_count }} / .stale_keys: how many issues matched and
their keys, semicolon-joined.{{ outputs.evaluate.values.severity }}: OK, SLA_BREACH, or CRITICAL.jql_filter is the entire governance policy; a typo in the JQL (an unknown field, a bad
operator) makes Jira return an error that this task surfaces via allowFailure, not a
silently empty result.maxResults: 50 caps the page size, but issues.Get pages through every result itself
until Jira reports no more, so size always reflects the true total match count, not just
the first page.-14d) is evaluated by Jira's own server clock at query time,
not by this flow; a project in a different timezone than expected can shift which issues
count as stale by up to a day.JIRA_API_TOKEN and SLACK_WEBHOOK_URL secrets.jira_base_url, jira_username, and jql_filter to a real project and policy.summary logs a count.jql_filter's date window until it matches a known stale issue, to confirm
alert fires with its key.daily trigger once jql_filter reflects your real SLA policy.jql_filter values with io.kestra.plugin.core.flow.Loop to enforce a
different staleness policy per project or issue type in one scheduled run.io.kestra.plugin.jira.issues.CreateComment on each matched issue to post a
"flagged as stale" note, gated behind an explicit confirm_comment input so commenting
never runs by accident.stale_keys by the fields.status.name already present in each row to route
different statuses to different Slack channels.