
Jira Epic Health Score & Risk Dashboard
Description
Categories
âď¸ Automation
Nodes Used
n8n-nodes-base.ifn8n-nodes-base.cronn8n-nodes-base.jiran8n-nodes-base.jiran8n-nodes-base.jiran8n-nodes-base.slackn8n-nodes-base.functionn8n-nodes-base.functionn8n-nodes-base.mondayComn8n-nodes-base.stickyNote
PriceFree
Views0
Last Updated11/28/2025
workflow.json
{
"id": "KwWlPZAiObwL1LOi",
"meta": {
"instanceId": "8443f10082278c46aa5cf3acf8ff0f70061a2c58bce76efac814b16290845177"
},
"name": "Jira Epic Health Score & Risk Dashboard",
"tags": [],
"nodes": [
{
"id": "5bb8e683-bde5-48d3-a424-1221f40f6580",
"name": "Trigger Every 6 Hours",
"type": "n8n-nodes-base.cron",
"position": [
-2864,
1360
],
"parameters": {
"triggerTimes": {
"item": [
{
"mode": "everyX",
"value": 6
}
]
}
},
"typeVersion": 1
},
{
"id": "a452f278-a5ea-443a-b98e-b33bb7d27aef",
"name": "đ Workflow Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3216,
1232
],
"parameters": {
"width": 280,
"height": 256,
"content": "đ WORKFLOW START\n\nThis workflow monitors Jira Epics and calculates health scores:\n\n⢠Runs every 6 hours\n⢠Fetches all Epics\n⢠Analyzes linked issues\n⢠Calculates health metrics\n⢠Flags at-risk epics\n⢠Updates dashboards\n⢠Alerts team via Slack"
},
"typeVersion": 1
},
{
"id": "e051afef-6cb0-45aa-b244-51baacd48602",
"name": "Fetch All Epics from Jira",
"type": "n8n-nodes-base.jira",
"position": [
-2608,
1360
],
"parameters": {
"options": {},
"operation": "getAll"
},
"credentials": {
"jiraSoftwareCloudApi": {
"id": "Q6d7sLBVOfGWmaLw",
"name": "Jira SW Cloud account vivek"
}
},
"typeVersion": 1
},
{
"id": "aef82a98-c0db-40f6-a3bb-a9df4535ec98",
"name": "đĽ Fetch Epics",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2752,
1088
],
"parameters": {
"width": 280,
"height": 236,
"content": "đĽ EPIC RETRIEVAL\n\nFetches all Epics from Jira:\n\n⢠Uses Jira REST API\n⢠getAll operation\n⢠Retrieves: Epic keys, names, fields\n⢠Filters to Epics only\n\nReturns list of all Epics in project\nPassed to Split Epics for processing"
},
"typeVersion": 1
},
{
"id": "1d172b8c-c88f-4ab5-b6ce-19110edcd433",
"name": "Split Epics for Processing",
"type": "n8n-nodes-base.function",
"position": [
-2368,
1360
],
"parameters": {
"functionCode": "const output = [];\nfor (const epic of items) {\n const key = epic.json.key;\n output.push({ json: { epicKey: key }});\n}\nreturn output;"
},
"typeVersion": 1
},
{
"id": "464b3b19-6f73-4a72-9dd4-8e77edb75439",
"name": "đ Split Epics",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2496,
1552
],
"parameters": {
"width": 280,
"height": 316,
"content": "đ SPLIT EPICS\n\nTransforms Epic batch into individual items:\n\n⢠Iterates through each Epic\n⢠Extracts Epic key\n⢠Creates separate object per Epic\n⢠Enables sequential processing\n\nInput: Array of Epics\nOutput: Individual Epic objects with key\n\nAllows detailed analysis per Epic"
},
"typeVersion": 1
},
{
"id": "63fe1ee2-e389-42f7-81ee-a8cf7fca80f7",
"name": "Fetch Epic + Linked Issues",
"type": "n8n-nodes-base.jira",
"position": [
-2112,
1360
],
"parameters": {
"issueKey": "={{ $json.epicKey }}",
"operation": "get",
"additionalFields": {}
},
"credentials": {
"jiraSoftwareCloudApi": {
"id": "Q6d7sLBVOfGWmaLw",
"name": "Jira SW Cloud account vivek"
}
},
"typeVersion": 1
},
{
"id": "0f47c09d-d22d-423e-9be4-e43fe3c39d0b",
"name": "đ Fetch Linked",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2208,
1024
],
"parameters": {
"width": 280,
"height": 300,
"content": "đ FETCH LINKED ISSUES\n\nFor each Epic, retrieves:\n\n⢠Epic metadata\n⢠All linked child issues\n⢠Issue details:\n â Status\n â Issue type (Bug/Task)\n â Labels (blocker, etc)\n â Cycle time metrics\n â Custom fields\n\nUsed to calculate health metrics"
},
"typeVersion": 1
},
{
"id": "750efdd8-c544-41ee-aa9c-ac3c11df107a",
"name": "Calculate Health Score",
"type": "n8n-nodes-base.function",
"position": [
-1856,
1360
],
"parameters": {
"functionCode": "const results = [];\n\nfor (const item of items) {\n const issues = item.json.issues || [];\n const total = issues.length || 1;\n\n let cycleTime = 0;\n let blockers = 0;\n let churn = 0;\n let bugs = 0;\n\n for (const issue of issues) {\n cycleTime += issue.fields.customfield_cycle_time || 0;\n if (issue.fields.labels && issue.fields.labels.includes('blocker')) blockers++;\n if (issue.fields.status && issue.fields.status.name === 'Reopened') churn++;\n if (issue.fields.issuetype && issue.fields.issuetype.name === 'Bug') bugs++;\n }\n\n const avgCycleTime = cycleTime / total;\n const bugRatio = bugs / total;\n const churnRatio = churn / total;\n const blockerRatio = blockers / total;\n\n // Weighted scoring\n const healthScore = (avgCycleTime * 0.4) + (bugRatio * 0.3) + (churnRatio * 0.2) + (blockerRatio * 0.1);\n\n results.push({\n json: {\n epicKey: item.json.epicKey || item.json.key,\n healthScore: Number(healthScore.toFixed(2))\n }\n });\n}\n\nreturn results;\n"
},
"typeVersion": 1
},
{
"id": "c8f3a361-a296-461d-93f8-3472d1f9f337",
"name": "đ Health Score",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1968,
1536
],
"parameters": {
"width": 280,
"height": 376,
"content": "đ HEALTH SCORE ALGORITHM\n\nWeighted formula (0-1 scale):\n\nmetrics calculated:\nâ avgCycleTime: Average days/hours\nâ bugRatio: Bugs / Total issues\nâ churnRatio: Reopened / Total\nâ blockerRatio: Blockers / Total\n\nWeights (importance):\n⢠avgCycleTime: 40% (velocity)\n⢠bugRatio: 30% (quality)\n⢠churnRatio: 20% (stability)\n⢠blockerRatio: 10% (dependencies)\n\nScore 0.0 = Healthy\nScore > 0.6 = At Risk â ď¸"
},
"typeVersion": 1
},
{
"id": "8aee7bd4-f155-4540-9598-d8923556673c",
"name": "Is Score > 0.6 (At Risk)?",
"type": "n8n-nodes-base.if",
"position": [
-1616,
1360
],
"parameters": {
"conditions": {
"number": [
{
"value1": "={{$json[\"healthScore\"]}}",
"value2": 0.6,
"operation": "larger"
}
]
}
},
"typeVersion": 1
},
{
"id": "e33d520e-955a-4ca2-9e11-1aaf8a078dfe",
"name": "â ď¸ Risk Check",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1792,
1008
],
"parameters": {
"width": 280,
"height": 316,
"content": "â ď¸ RISK THRESHOLD\n\nCondition: healthScore > 0.6\n\nInterpretation:\n⢠Score 0.0-0.6 = Healthy â
\n⢠Score > 0.6 = At Risk â ď¸\n\nIf AT RISK:\nâ Update Epic in Jira\nâ Add \"At Risk\" label\nâ Alert team via Slack\nâ Log to Monday & Sheets\n\nIf HEALTHY:\nâ No action needed"
},
"typeVersion": 1
},
{
"id": "7a14fe1b-bd86-4040-8655-0e8d48f5e35e",
"name": "Update Epic in Jira",
"type": "n8n-nodes-base.jira",
"position": [
-1344,
1024
],
"parameters": {
"issueKey": "={{$json[\"epicKey\"]}}",
"operation": "update",
"updateFields": {
"labels": [
"At Risk"
],
"customFieldsUi": {
"customFieldsValues": [
{
"fieldId": "customfield_10060",
"fieldValue": "={{$json[\"healthScore\"]}}"
}
]
}
}
},
"credentials": {
"jiraSoftwareCloudApi": {
"id": "Q6d7sLBVOfGWmaLw",
"name": "Jira SW Cloud account vivek"
}
},
"typeVersion": 1
},
{
"id": "dc4eba68-ee7f-4226-8369-3fdeaf7806d7",
"name": "đ Jira Update",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1440,
720
],
"parameters": {
"width": 280,
"height": 268,
"content": "đ JIRA UPDATE\n\nUpdates at-risk Epic:\n\n⢠Sets custom field:\n customfield_10060 = Health Score\n⢠Adds label: \"At Risk\"\n⢠Creates audit trail\n⢠Visible in Epic view\n\nTeam sees risk status immediately in Jira\nEnables auto-filtering by label"
},
"typeVersion": 1
},
{
"id": "48ef861d-0de4-4424-b453-a5a26f94716f",
"name": "Alert Slack Channel",
"type": "n8n-nodes-base.slack",
"position": [
-1360,
1200
],
"parameters": {
"text": "đ¨ *Epic At Risk:* {{$json[\"epicKey\"]}}\nHealth Score: {{$json[\"healthScore\"]}}\nhttps://yourdomain.atlassian.net/browse/{{$json[\"epicKey\"]}}",
"channel": "#project-alerts",
"attachments": [],
"otherOptions": {}
},
"credentials": {
"slackApi": {
"id": null,
"name": "Your Slack Credential"
}
},
"typeVersion": 1
},
{
"id": "822fc9ef-2efe-45a5-9bdf-4d4cd5bc14a2",
"name": "đ¨ Slack Alert",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1168,
1168
],
"parameters": {
"width": 280,
"height": 268,
"content": "đ¨ SLACK ALERT\n\nSends to: #project-alerts\n\nContains:\nâ Epic key\nâ Health score value\nâ Direct link to Epic in Jira\nâ Timestamp (automatic)\n\nEnables real-time team notification\nCritical for risk mitigation\nAllows quick team action"
},
"typeVersion": 1
},
{
"id": "cd79db68-7aad-43bf-a436-75e377daa0fa",
"name": "Update Monday.com Pulse",
"type": "n8n-nodes-base.mondayCom",
"position": [
-1280,
1552
],
"parameters": {
"operation": "update"
},
"credentials": {
"mondayComApi": {
"id": null,
"name": "Your Monday Credential"
}
},
"typeVersion": 1
},
{
"id": "03da2282-3393-4c2d-b81b-66d8527e2873",
"name": "đ Monday Pulse",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1072,
1488
],
"parameters": {
"width": 280,
"height": 300,
"content": "đ MONDAY.COM PULSE\n\nUpdates Monday.com board with:\n\n⢠Health score metric\n⢠Risk status\n⢠Last updated timestamp\n\nSyncs data across platforms\nKeeps Monday boards current\nPulse shows real-time metrics\n\nNote: Requires Monday.com credential setup"
},
"typeVersion": 1
},
{
"id": "716d2c3b-5cc4-4358-8f1a-c89844774af6",
"name": "Log to Google Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
-1280,
1760
],
"parameters": {
"range": "A:C",
"options": {
"valueInputMode": "USER_ENTERED"
},
"sheetId": "Your Google Sheet ID",
"operation": "append"
},
"credentials": {
"googleApi": {
"id": null,
"name": "Your Google Credential"
}
},
"typeVersion": 1
},
{
"id": "41c60824-3019-4cc1-8284-1ca48deb52f4",
"name": "đ Sheets Log",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1408,
1920
],
"parameters": {
"width": 280,
"height": 332,
"content": "đ GOOGLE SHEETS LOG\n\nAppends historical record:\n\nColumns (A:C):\nâ Timestamp\nâ Epic Key\nâ Health Score\n\nUsed for:\n⢠Trend analysis\n⢠Risk history\n⢠Compliance audit\n⢠Dashboard creation\n⢠Performance tracking\n\nBuilds dataset over time"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "258c9a43-6f98-43c1-bbe4-91090329165b",
"connections": {
"Trigger Every 6 Hours": {
"main": [
[
{
"node": "Fetch All Epics from Jira",
"type": "main",
"index": 0
}
]
]
},
"Calculate Health Score": {
"main": [
[
{
"node": "Is Score > 0.6 (At Risk)?",
"type": "main",
"index": 0
}
]
]
},
"Fetch All Epics from Jira": {
"main": [
[
{
"node": "Split Epics for Processing",
"type": "main",
"index": 0
}
]
]
},
"Is Score > 0.6 (At Risk)?": {
"main": [
[
{
"node": "Update Epic in Jira",
"type": "main",
"index": 0
},
{
"node": "Alert Slack Channel",
"type": "main",
"index": 0
}
],
[
{
"node": "Update Monday.com Pulse",
"type": "main",
"index": 0
},
{
"node": "Log to Google Sheets",
"type": "main",
"index": 0
}
]
]
},
"Fetch Epic + Linked Issues": {
"main": [
[
{
"node": "Calculate Health Score",
"type": "main",
"index": 0
}
]
]
},
"Split Epics for Processing": {
"main": [
[
{
"node": "Fetch Epic + Linked Issues",
"type": "main",
"index": 0
}
]
]
}
}
}