opsintermediate10 min setupby Mantle

Daily Jira bug digest to Slack

Every morning, search Jira for open bugs and post the count and the list to a Slack channel.

Every weekday 09Open bugsPost the digest

Drag to pan, pinch to zoom. This is the real graph the template installs.

Purpose

Every morning, search Jira for open bugs and post the count and the list to a Slack channel.

How it works

What it does

  • Runs at 09:00 on weekdays.
  • Searches Jira with a JQL query for open bugs (one retry after 3 s if Jira is slow).
  • Posts the total, the number shown and the issue list to a Slack channel.

Validation

This template is contract-validated: the unit suite checks every node type, every config key and the whole graph against the same rules a saved workflow passes. It has not been run against the live provider — the ids, names and columns below are placeholders to replace with your own.

Nodes 3

  1. 01Every weekday 09:00trigger.scheduleTrigger
  2. 02Open bugsjira.search_issuesApp
  3. 03Post the digestslack.post_messageApp
View template JSON
{
  "format": "mantle-workflow/v1",
  "id": "slack-jira-bug-digest",
  "name": "Daily Jira bug digest to Slack",
  "graph": {
    "nodes": [
      {
        "id": "cron",
        "type": "trigger.schedule",
        "label": "Every weekday 09:00",
        "config": {
          "cron_expr": "0 9 * * 1-5",
          "timezone": "UTC"
        },
        "worker_type": "generic-worker",
        "position": {
          "x": 60,
          "y": 220
        }
      },
      {
        "id": "bugs",
        "type": "jira.search_issues",
        "label": "Open bugs",
        "config": {
          "jql": "project = ENG AND issuetype = Bug AND statusCategory != Done ORDER BY priority DESC",
          "max_results": 25,
          "fields": "summary,status,priority,assignee"
        },
        "worker_type": "generic-worker",
        "position": {
          "x": 380,
          "y": 220
        },
        "retry": {
          "max_attempts": 2,
          "backoff": "fixed",
          "initial_ms": 3000,
          "max_ms": 3000
        }
      },
      {
        "id": "post",
        "type": "slack.post_message",
        "label": "Post the digest",
        "config": {
          "channel": "#eng-standup",
          "text": "*Open bugs: {{ steps.bugs.total }}* (showing {{ steps.bugs.count }})\n```{{ steps.bugs.issues }}```"
        },
        "worker_type": "generic-worker",
        "position": {
          "x": 700,
          "y": 220
        }
      }
    ],
    "edges": [
      {
        "from": "cron",
        "to": "bugs"
      },
      {
        "from": "bugs",
        "to": "post"
      }
    ]
  }
}

Requirements

The connections and permissions each step needs, from the node contracts in the catalog.

  • JiraUsername & password

    Used by Open bugs.

    Credential: {"email", "api_token"}

    • Atlassian removed GET /rest/api/3/search (CHANGE-2046); this node now calls GET /rest/api/3/search/jql. The node type, its config keys and the issues/count/total output keys are unchanged, but the replacement endpoint reports no result-set total, so 'total' is the size of the page returned.
    • Paging is by next_page_token, not by an offset: feed next_page_token back in as page_token to read the following page.
  • SlackAPI key

    Used by Post the digest.

    Credential: the bot token (xoxb-…), or {"token": "xoxb-…"}

    • The bot must be a member of a private channel before it can post there (Slack error not_in_channel otherwise).

Setup

  • Set jql to your project and your definition of open; max_results caps the list.
  • Pick a Jira connection (its domain config key is your your-org.atlassian.net) and a Slack connection, then set the channel.
  • Change cron_expr for a different time — it is read in the trigger's timezone.

Sample input and output

Synthetic examples: node-contract samples or placeholders, never customer data.

Input

Runs on the cron schedule 0 9 * * 1-5 (UTC). There is no incoming payload: the first step fetches the data.

Output

Post the digest slack.post_message

{
  "channel": "",
  "ok": true,
  "ts": ""
}

Failure handling

What the graph does when a step fails, read from its retry settings, error branches and error policies.

  • Open bugs: up to 2 attempts, 3 s between attempts.
  • A step that fails, after any retries, fails the run. The failed step is kept with its input and error.

See it run, then make it yours.

Templates install as drafts. Edit any step, and Workflow Health re-checks the graph on every save.