Send notification when an issue is added or removed from a sprint

Platform Notice: Cloud and Data Center - This article applies equally to both cloud and data center platforms.

Support for Server* products ended on February 15th 2024. If you are running a Server product, you can visit the Atlassian Server end of support announcement to review your migration options.

*Except Fisheye and Crucible

Summary

This article provides an Automation for Jira (A4J) rule that will send an email whenever an issue is added or removed from the Active Sprint. The solution works in both Jira Cloud and Data Center/Server versions (running A4J 9.0.3 or later). There are examples of exported rules and demo videos for Cloud and Data Center versions at the end of the article.

NOTE: Parallel sprints feature disabled (this has not been tested with Parallel Sprints enabled and may not work with this functionality enabled)

Solution

Implementation

Premise

a. There can be only one sprint change per rule triggered. b. The UI and REST API allow only one sprint change per issue update. c. An issue's sprint field can have multiple closed (completed) and (zero or one active or future) sprints.

When sprint has changed the A4J smart value fieldChange will have the following:

  • "{{fieldChange.from}}" = the issue's previous sprint IDs

  • "{{fieldChange.to}}" = the issue's current sprint IDs

Methods

The solution utilizes the following:

  • Jira Agile REST API call (Web Request) to get a sprint's state and then use it in a condition to determine whether to send a notification.

  • Issue's "{{fieldChange.to}}" and "{{fieldChange.from}}" strings that have comma delimited sprint IDs that tells us the issue was moved and/or added to another sprint

  • Set theory and basic math - We use basic math and smart value List functions to perform basic Set union and intersections to find the 'changed' sprint.

Most difficult use-case

  • from: closed-sprint-1, active-sprint, closed-sprint-2

  • to: closed-sprint-1, closed-sprint-2, future-sprint

The fieldChange of Sprint IDs are sorted, so the 'changed' sprint could be in the middle of the list of IDs in either 'from' or 'to' list. There is loop (Advanced Branching) in A4J DC version.

High level steps in the rule

1) build the list with a '0' sprint ID anchor - we need this because A4J does understand an empty list - it will set it to null. So, we must have at least one element in the list

fromList = "0" + "{{fieldChange.to}} toList = "0" + "{{fieldChange.to}}

2) Union the lists - merge the lists to build a set of distinct sprint ids mergedList = distinct(fromtList + toList)

3) Find the sprint that was removed or added to the issue. The premise is that there could be only one change per Issue update, which is true currently in the UI and also REST API - we can only add or remove one non-completed sprint per issue update. Also, an issue can have at most one non-completed sprint (e.g., Open or Future).

removedSprintId = mergedList - toList newSprintId = mergedList - fromList

4) notify sprint is added

  • If newSprintId is not null then

  • newSprint = HTTP GET /agile/1.0/sprint/<newSprintId>

  • If newSprint.state is active then

  • notify issue has been added to the sprint

5) notify sprint is removed

  • If removedSprintId is not null then

  • removedSprint = HTTP GET /agile/1.0/sprint/<removedSprintId>

  • If removedSprint.state is active then

  • notify issue has been removed from the sprint

We use two IF-statements instead of IF-THEN-ELSE, because we don't know the changed sprint is active or future until we make the REST API call to find it's info. We want to minimize REST API calls to only.

Also, it's important when making the REST API call, we check the "Delay execution of subsequent rule actions until we've received a response for this webhook" option to ensure we have the sprint object before proceeding with the rule execution, else subsequent logic will fail because the sprint object will be null.

Sprint REST API

The REST API to get a single sprint's information is GET /rest/agile/1.0/sprint/{sprintId}

Set up the Web Request

The steps are in the KB article "How to extend Automation for Jira with REST API calls."

We need the following;

We must wait for the REST API response.

Delay in execution of subsequent rule action untill we have received a response

Accessing the REST API Response Data

The results of a successful web request will be a single Sprint record stored in the smart value "{{webhookResponse.body}}." The following example is from a REST API call that returns Sprint record with ID = 4:

1 2 3 4 5 6 7 8 9 10 11 12 curl -s -u scrummaster:mypassword -X GET "http://localhost:42010/j82010/rest/agile/1.0/sprint/4" | python3 -mjson.tool { "id": 4, "self": "http://localhost:42010/j82010/rest/agile/1.0/sprint/4", "state": "active", "name": "ActiveSprint", "startDate": "2023-12-01T19:33:00.000-08:00", "endDate": "2023-12-31T19:33:00.000-08:00", "activatedDate": "2023-12-06T19:45:01.005-08:00", "originBoardId": 8, "goal": "Dec-2023 " }

We can access the Sprint data fields using the following smart values:

1 2 3 4 5 6 7 8 9 {{webhookResponse.body.id}} {{webhookResponse.body.self}} {{webhookResponse.body.state}} {{webhookResponse.body.name}} {{webhookResponse.body.startDate}} {{webhookResponse.body.endDate}} {{webhookResponse.body.activatedDate}} {{webhookResponse.body.originBoardId}} {{webhookResponse.body.goal}}

Automation Rule

Automation to send notification when an issue is added or removed from a sprit
Automation to send notification when an issue is added or removed from a sprit
Automation to send notification when an issue is added or removed from a sprint

Examples

Both Jira Cloud and Data Center version examples are essentially the same. The primary rule implementation is the same. The UI is different, and the exported rules are incompatible. Therefore, we need two sets of example exported rules. Both examples use API tokens for authentication in the rule Web Request calls to Jira. The implementation of notification is using Web Request to a public site 'webhook.site' that provides a free web server. The notification can be changed to email, slack, or other websites using the same smart values.

Data Center version

The example exported rule uses Web Request action for the notification and my localhost Jira site. To implement it in your environment

  • update the Notification components for your org., for example, change to email, slack, or log action in the rule audit log.

  • update the web request that gets the sprint information via REST API with your Jira instance with the correct base URL and bearer token.

    • Automation rule add remove issue from active sprint JSON

      1 {"rules":[{"id":39,"clientKey":"com.codebarrel.tenant.global","name":"Issue Added/Removed from Active Sprint (v4)","state":"ENABLED","description":"Send a notification when an issue is added or removed from an active sprint.\n\nPremise\na. This has not been tested with parallel sprints enabled\nb. There can be only one sprint change per rule triggered. \nc. The UI and REST API allow only one sprint change per issue update.\nd. Tested using Jira 8.20.10 and A4J 9.0.3 with limited scenarios\ne. An issue's sprint field can have multiple closed (completed) and (zero or one active or future) sprints.\n\n\nScenario:\n\nSprints ID. state\n----------------+---------------\n1 completed\n3 future\n4 active\n5 completed \n\n1. simple active\n EMPTY -> 4 >>> send notification that issue has been added to 4\n 4. -> EMPTY >>> send notification that issue has been removed from 4\n\n2. simple active,closed\n\n 1 -> 1,4 >>> send notification that issue has been added to 4\n 1,4 -> 1 >>> send notification that issue has been removed from 4\n\n3. simple active, 2x closed\n\n 1,5 -> 1,4,5 >>> send notification that issue has been added to 4\n 1,4,5 -> 1,5 >>> send notification that issue has been removed from 4\n\n4. simple future (no notifications)\n\n EMPTY -> 3 >>> no notification \n 3 -> EMPTY >>> no notification \n\n5. simple future,closed\n\n 1 -> 1,3 >>> no notification\n 1,3 -> 1 >>> no notification\n\n6. simple future, 2x closed\n\n 1,5 -> 1,3,5 >>> no notification\n 1,3,5 -> 1,5 >>> no notification\n\n7. move between future and active:\n 1,3 -> 1,4 >>> send notification that issue has been added to 4\n 1,4 -> 1,3 >>> send notification that issue has been removed from 4\n 1,3,5 -> 1,4,5 >>> send notification that issue has been added to 4\n 1,4,5 -> 1,3,5 >>> send notification that issue has been removed from 4\n\n-----------------------------------\n\nCan add these to check my variable values in a notification action prior the main IF block:\n\nTEST My variables\n\nissue.key = {{issue.key}}\nfieldChange {{fieldChange}}\n===============\nanchor = {{anchor}}\nfrom.List = {{fromList}}\nfromListSize = {{fromListSize}}\nfromListSum = {{fromListSum}}\ntoList = {{toList}} \ntoListSize={{toListSize}}\ntoListSum = {{toListSum}}\n-------\nmergedSprintsString = {{mergedSprintsString}}\nmergedSprintsList = {{{{mergedSprintsString.split(',').distinct}}\nmergedListSprintsSum = {{mergedSprintsListSum}}\npreviousSprintID = {{previousSprintID}}\ncurrentSprintID = {{currentSprintID}}\n--------\ncheckAdd = {{checkAdd}}. \ncheckRemove = {{checkRemove}}\n\n-------------------------\n\nif checkAdd >= 0 {\n if new sprint is active {\n send notification\n }\n}\n\nif checkRemove >= 0 {\n if new sprint is active {\n send notification\n }\n}\n\n-----------------------------------\n\nselect \"ID\", \"NAME\", \"STARTED\", \"CLOSED\" from \"AO_60DB71_SPRINT\" order by \"ID\";\n ID | NAME | STARTED | CLOSED \n----+--------------------------+---------+--------\n 1 | Nov-2023 | t | t\n 2 | Sample Sprint 1 | t | t\n 3 | FutureSprint | f | f\n 4 | ActiveSprint | t | f\n 5 | short sprint Dec 11 only | t | t\n(5 rows)\n\nclosed sprint = STARTED && CLOSED\nopen sprint = STARTED && !CLOSED\nfuture sprint = !STARTED && !CLOSED\n\n---------------\n\n% curl -s -u username:password -X GET \"http://localhost:42010/j82010/rest/api/latest/issue/SP-32\" | python3 -mjson.tool | grep -B1 \"com.atlassian.greenhopper.service.sprint.Sprint\"\n\n\"customfield_10106\": [ \n\n\"com.atlassian.greenhopper.service.sprint.Sprint@3478edbe[id=1,rapidViewId=1,state=CLOSED,name=Nov-2023,startDate=2023-11-01T01:18:00.000-07:00,endDate=2023-11-30T01:38:00.000-08:00,completeDate=2023-12-08T14:36:44.069-08:00,activatedDate=2023-02-03T01:18:22.593-08:00,sequence=1,goal=<null>,autoStartStop=false]\", \n\n\"com.atlassian.greenhopper.service.sprint.Sprint@5255fc4c[id=4,rapidViewId=8,state=ACTIVE,name=ActiveSprint,startDate=2023-12-01T19:33:00.000-08:00,endDate=2023-12-31T19:33:00.000-08:00,completeDate=<null>,activatedDate=2023-12-06T19:45:01.005-08:00,sequence=4,goal=Dec-2023 ,autoStartStop=false]\", \n\n\"com.atlassian.greenhopper.service.sprint.Sprint@68447f13[id=5,rapidViewId=8,state=CLOSED,name=short sprint Dec 11 only,startDate=2023-12-11T03:48:00.000-08:00,endDate=2023-12-11T16:00:00.000-08:00,completeDate=2023-12-11T16:00:05.489-08:00,activatedDate=2023-12-11T15:56:42.006-08:00,sequence=5,goal=,autoStartStop=false]\"","canOtherRuleTrigger":false,"notifyOnError":"NEVER","authorAccountId":"JIRAUSER10000","actorAccountId":"JIRAUSER10000","created":1702487161767,"updated":1702490122370,"trigger":{"id":"5563","component":"TRIGGER","schemaVersion":2,"type":"jira.issue.field.changed","value":{"synchronous":false,"fields":[{"value":"customfield_10106","type":"field"}],"actions":[]},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false},"components":[{"id":"5564","component":"ACTION","schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702452982311","name":{"type":"FREE","value":"anchor"},"type":"SMART","query":{"type":"SMART","value":"0,"},"lazy":false},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false},{"id":"5565","component":"ACTION","schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702449582115","name":{"type":"FREE","value":"fromList"},"type":"SMART","query":{"type":"SMART","value":"{{anchor.concat(fieldChange.from).split(',')}}"},"lazy":false},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false},{"id":"5566","component":"ACTION","schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702465879402","name":{"type":"FREE","value":"fromListSize"},"type":"SMART","query":{"type":"SMART","value":"{{#=}}{{anchor.concat(fieldChange.from).split(',').size}}{{/}}"},"lazy":false},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false},{"id":"5567","component":"ACTION","schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702372354065","name":{"type":"FREE","value":"fromListSum"},"type":"SMART","query":{"type":"SMART","value":"{{anchor.concat(fieldChange.from).split(',').sum.floor}}"},"lazy":false},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false},{"id":"5568","component":"ACTION","schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702449665257","name":{"type":"FREE","value":"toList"},"type":"SMART","query":{"type":"SMART","value":"{{anchor.concat(fieldChange.to).split(',')}}"},"lazy":false},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false},{"id":"5569","component":"ACTION","schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702465911403","name":{"type":"FREE","value":"toListSize"},"type":"SMART","query":{"type":"SMART","value":"{{#=}}{{anchor.concat(fieldChange.to).split(',').size}}{{/}}"},"lazy":false},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false},{"id":"5570","component":"ACTION","schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702372391432","name":{"type":"FREE","value":"toListSum"},"type":"SMART","query":{"type":"SMART","value":"{{anchor.concat(fieldChange.to).split(',').sum.floor}}"},"lazy":false},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false},{"id":"5571","component":"ACTION","schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702434584284","name":{"type":"FREE","value":"mergedSprintsString"},"type":"SMART","query":{"type":"SMART","value":"{{anchor.concat(fieldChange.from).concat(\",\").concat(anchor.concat(fieldChange.to)).remove(\" \")}}"},"lazy":false},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false},{"id":"5572","component":"ACTION","schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702442284171","name":{"type":"FREE","value":"mergedSprintsListSum"},"type":"SMART","query":{"type":"SMART","value":"{{mergedSprintsString.split(',').distinct.sum}}"},"lazy":false},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false},{"id":"5573","component":"ACTION","schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702455209130","name":{"type":"FREE","value":"previousSprintID"},"type":"SMART","query":{"type":"SMART","value":"{{#=}}{{mergedSprintsListSum}}-{{toListSum}}{{/}}"},"lazy":false},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false},{"id":"5574","component":"ACTION","schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702455348543","name":{"type":"FREE","value":"currentSprintID"},"type":"SMART","query":{"type":"SMART","value":"{{#=}}{{mergedSprintsListSum}}-{{fromListSum}}{{/}}"},"lazy":false},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false},{"id":"5575","component":"ACTION","schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702463652061","name":{"type":"FREE","value":"checkAdd"},"type":"SMART","query":{"type":"SMART","value":"{{#=}}{{toListSize}}-{{fromListSize}}{{/}}"},"lazy":false},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false},{"id":"5576","component":"ACTION","schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702463716250","name":{"type":"FREE","value":"checkRemove"},"type":"SMART","query":{"type":"SMART","value":"{{#=}}{{fromListSize}}-{{toListSize}}{{/}}"},"lazy":false},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false},{"id":"5577","component":"ACTION","schemaVersion":2,"type":"jira.issue.outgoing.webhook","value":{"url":"https://webhook.site/87d69382-8c6e-4877-8056-0297c8089e88","headers":[{"id":"_header_1702288366811","name":"","value":{"keyOrValue":"","secret":false}}],"sendIssue":false,"contentType":"custom","customBody":"TEST My variables\n\nissue.key = {{issue.key}}\nfieldChange {{fieldChange}}\n===============\nanchor = {{anchor}}\nfrom.List = {{fromList}}\nfromListSize = {{fromListSize}}\nfromListSum = {{fromListSum}}\ntoList = {{toList}} \ntoListSize={{toListSize}}\ntoListSum = {{toListSum}}\n-------\nmergedSprintsString = {{mergedSprintsString}}\nmergedSprintsList = {{mergedSprintsString.split(',').distinct}}\nmergedListSprintsSum = {{mergedSprintsListSum}}\npreviousSprintID = {{previousSprintID}}\ncurrentSprintID = {{currentSprintID}}\n--------\ncheckAdd = {{checkAdd}}. \ncheckRemove = {{checkRemove}}\n\n-------------------------\nNotes:\n\nif checkAdd >= 0 {\n if new sprint is active {\n send notification\n }\n}\n\nif checkRemove >= 0 {\n if new sprint is active {\n send notification\n }\n}\n\n","method":"POST","responseEnabled":false,"usedSecretsKeys":[]},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false},{"id":"5578","component":"BRANCH","schemaVersion":1,"type":"jira.issue.related","value":{"relatedType":"current","jql":"","linkTypes":[],"onlyUpdatedIssues":false,"processIssuesInBulk":false},"children":[{"id":"5579","component":"CONDITION","parentId":"5578","schemaVersion":1,"type":"jira.comparator.condition","value":{"first":"{{checkAdd}}","second":"-1","operator":"GREATER_THAN"},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false},{"id":"5580","component":"ACTION","parentId":"5578","schemaVersion":2,"type":"jira.issue.outgoing.webhook","value":{"url":"http://localhost:42010/j82010/rest/agile/1.0/sprint/{{currentSprintID}}","headers":[{"id":"_header_1701949243211","name":"Authorization","value":{"keyOrValue":"Bearer MTE0NTk5MjM5MTM1Ohg2tih+m5cX3gW0IGMh+sFxp0Hc","secret":false}}],"sendIssue":false,"contentType":"empty","method":"GET","responseEnabled":true,"usedSecretsKeys":[]},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false},{"id":"5581","component":"ACTION","parentId":"5578","schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702251014615","name":{"type":"FREE","value":"currentSprintState"},"type":"SMART","query":{"type":"SMART","value":"{{webhookResponse.body.state}}"},"lazy":false},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false},{"id":"5582","component":"CONDITION","parentId":"5578","schemaVersion":1,"type":"jira.comparator.condition","value":{"first":"{{currentSprintState}}","second":"active","operator":"EQUALS"},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false},{"id":"5583","component":"ACTION","parentId":"5578","schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702469748807","name":{"type":"FREE","value":"sprintName"},"type":"SMART","query":{"type":"SMART","value":"{{webhookResponse.body.name}}"},"lazy":false},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false},{"id":"5584","component":"ACTION","parentId":"5578","schemaVersion":2,"type":"jira.issue.outgoing.webhook","value":{"url":"https://webhook.site/87d69382-8c6e-4877-8056-0297c8089e88","headers":[{"id":"_header_1701917180984","name":"Authorization","value":{"keyOrValue":"Bearer x","secret":false}}],"sendIssue":false,"contentType":"custom","customBody":"{{now .convertToTimeZone(\"America/Los_Angeles\").longDateTime}}:\nAdded {{issue.key}} to active sprint '{{sprintName}}'\n\nOld Issue Sprint: '[{{fieldChange.fromString}}]'\nNew Issue Sprint: '[{{fieldChange.toString}}]'\n","method":"POST","responseEnabled":false,"usedSecretsKeys":[]},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false}],"conditions":[],"optimisedIds":[],"newComponent":false},{"id":"5585","component":"CONDITION","schemaVersion":1,"type":"jira.condition.container.block","children":[{"id":"5586","component":"CONDITION_BLOCK","parentId":"5585","schemaVersion":1,"type":"jira.condition.if.block","value":{"conditionMatchType":"ALL"},"children":[{"id":"5588","component":"ACTION","parentId":"5586","schemaVersion":2,"type":"jira.issue.outgoing.webhook","value":{"url":"http://localhost:42010/j82010/rest/agile/1.0/sprint/{{previousSprintID}}","headers":[{"id":"_header_1701946642254","name":"Authorization","value":{"keyOrValue":"Bearer MTE0NTk5MjM5MTM1Ohg2tih+m5cX3gW0IGMh+sFxp0Hc","secret":false}}],"sendIssue":false,"contentType":"empty","method":"GET","responseEnabled":true,"usedSecretsKeys":[]},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false},{"id":"5589","component":"ACTION","parentId":"5586","schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1701947930023","name":{"type":"FREE","value":"previousSprintState"},"type":"SMART","query":{"type":"SMART","value":"{{webhookResponse.body.state}}"},"lazy":false},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false},{"id":"5590","component":"CONDITION","parentId":"5586","schemaVersion":1,"type":"jira.comparator.condition","value":{"first":"{{previousSprintState}}","second":"active","operator":"EQUALS"},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false},{"id":"5591","component":"ACTION","parentId":"5586","schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702469652306","name":{"type":"FREE","value":"sprintName"},"type":"SMART","query":{"type":"SMART","value":"{{webhookResponse.body.name}}"},"lazy":false},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false},{"id":"5592","component":"ACTION","parentId":"5586","schemaVersion":2,"type":"jira.issue.outgoing.webhook","value":{"url":"https://webhook.site/87d69382-8c6e-4877-8056-0297c8089e88","headers":[{"id":"_header_1701912785834","name":"","value":{"keyOrValue":"","secret":false}}],"sendIssue":false,"contentType":"custom","customBody":"{{now.convertToTimeZone(\"America/Los_Angeles\").longDateTime}}:\nRemoved issue {{issue.key}} from active sprint '{{sprintName}}'\n\nIssue Sprint: '[{{issue.sprint}}]'\nfieldChange.to : '{{fieldChange.toString}}'\nfieldChange.from : '{{fieldChange.fromString}}'\nprevious sprint state: '{{previousSprintState}}'","method":"POST","responseEnabled":false,"usedSecretsKeys":[]},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false}],"conditions":[{"id":"5587","component":"CONDITION","conditionParentId":"5586","schemaVersion":1,"type":"jira.comparator.condition","value":{"first":"{{checkRemove}}","second":"-1","operator":"GREATER_THAN"},"children":[],"conditions":[],"optimisedIds":[],"newComponent":false}],"optimisedIds":[],"newComponent":false}],"conditions":[],"optimisedIds":[],"newComponent":false}],"projects":[],"labels":[],"tags":[]}],"cloud":false}

  • Cloud version

    The example exported rule uses Web Request action for the notification and my localhost Jira site. To implement it in your environment

    • update the Notification components for your org., for example, change to email, slack, or log action in the rule audit log.

    • update the web request that gets the sprint information via REST API to your Jira instance with the correct base URL and basic authentication token - see this article on how to create a token for Jira Cloud basic authentication

    • Automation rule to send a notification when the issue is added or removed from sprint JSON:

      1 {"cloud":true,"rules":[{"id":17203407,"clientKey":"a34b2254-4bdb-3129-80ae-4969d95c3851","name":"Issue Added/Removed from Active Sprint (Cloud)","state":"ENABLED","description":"Send a notification when an issue is added or removed from an active sprint.\n\nPremise\na. This has not been tested with parallel sprints enabled\nb. There can be only one sprint change per rule triggered. \nc. The UI and REST API allow only one sprint change per issue update.\nd. Tested using Jira 8.20.10 and A4J 9.0.3 with limited scenarios\ne. An issue's sprint field can have multiple closed (completed) and (zero or one active or future) sprints.\n\n\nScenario:\n\nSprints ID. state\n----------------+---------------\n1 completed\n3 future\n4 active\n5 completed \n\n1. simple active\n EMPTY -> 4 >>> send notification that issue has been added to 4\n 4. -> EMPTY >>> send notification that issue has been removed from 4\n\n2. simple active,closed\n\n 1 -> 1,4 >>> send notification that issue has been added to 4\n 1,4 -> 1 >>> send notification that issue has been removed from 4\n\n3. simple active, 2x closed\n\n 1,5 -> 1,4,5 >>> send notification that issue has been added to 4\n 1,4,5 -> 1,5 >>> send notification that issue has been removed from 4\n\n4. simple future (no notifications)\n\n EMPTY -> 3 >>> no notification \n 3 -> EMPTY >>> no notification \n\n5. simple future,closed\n\n 1 -> 1,3 >>> no notification\n 1,3 -> 1 >>> no notification\n\n6. simple future, 2x closed\n\n 1,5 -> 1,3,5 >>> no notification\n 1,3,5 -> 1,5 >>> no notification\n\n7. move between future and active:\n 1,3 -> 1,4 >>> send notification that issue has been added to 4\n 1,4 -> 1,3 >>> send notification that issue has been removed from 4\n 1,3,5 -> 1,4,5 >>> send notification that issue has been added to 4\n 1,4,5 -> 1,3,5 >>> send notification that issue has been removed from 4\n\n-----------------------------------\n\nCan add these to check my variable values in a notification action prior to the main IF block:\n\nTEST My variables\n\nissue.key = {{issue.key}}\nfieldChange {{fieldChange}}\n===============\nanchor = {{anchor}}\nfrom.List = {{fromList}}\nfromListSize = {{fromListSize}}\nfromListSum = {{fromListSum}}\ntoList = {{toList}} \ntoListSize={{toListSize}}\ntoListSum = {{toListSum}}\n-------\nmergedSprintsString = {{mergedSprintsString}}\nmergedSprintsList = {{{{mergedSprintsString.split(',').distinct}}\nmergedListSprintsSum = {{mergedSprintsListSum}}\npreviousSprintID = {{previousSprintID}}\ncurrentSprintID = {{currentSprintID}}\n--------\ncheckAdd = {{checkAdd}}. \ncheckRemove = {{checkRemove}}\n\n-------------------------\n\nif checkAdd >= 0 {\n if new sprint is active {\n send notification\n }\n}\n\nif checkRemove >= 0 {\n if new sprint is active {\n send notification\n }\n}\n\n-----------------------------------\n\nSample Data (from test Data Center environment):\n\nselect \"ID\", \"NAME\", \"STARTED\", \"CLOSED\" from \"AO_60DB71_SPRINT\" order by \"ID\";\n ID | NAME | STARTED | CLOSED \n----+--------------------------+---------+--------\n 1 | Nov-2023 | t | t\n 2 | Sample Sprint 1 | t | t\n 3 | FutureSprint | f | f\n 4 | ActiveSprint | t | f\n 5 | short sprint Dec 11 only | t | t\n(5 rows)\n\nclosed sprint = STARTED && CLOSED\nopen sprint = STARTED && !CLOSED\nfuture sprint = !STARTED && !CLOSED\n\n---------------\n\n% curl -s -u username:password -X GET \"http://localhost:42010/j82010/rest/api/latest/issue/SP-32\" | python3 -mjson.tool | grep -B1 \"com.atlassian.greenhopper.service.sprint.Sprint\"\n\n\"customfield_10106\": [ \n\n\"com.atlassian.greenhopper.service.sprint.Sprint@3478edbe[id=1,rapidViewId=1,state=CLOSED,name=Nov-2023,startDate=2023-11-01T01:18:00.000-07:00,endDate=2023-11-30T01:38:00.000-08:00,completeDate=2023-12-08T14:36:44.069-08:00,activatedDate=2023-02-03T01:18:22.593-08:00,sequence=1,goal=<null>,autoStartStop=false]\", \n\n\"com.atlassian.greenhopper.service.sprint.Sprint@5255fc4c[id=4,rapidViewId=8,state=ACTIVE,name=ActiveSprint,startDate=2023-12-01T19:33:00.000-08:00,endDate=2023-12-31T19:33:00.000-08:00,completeDate=<null>,activatedDate=2023-12-06T19:45:01.005-08:00,sequence=4,goal=Dec-2023 ,autoStartStop=false]\", \n\n\"com.atlassian.greenhopper.service.sprint.Sprint@68447f13[id=5,rapidViewId=8,state=CLOSED,name=short sprint Dec 11 only,startDate=2023-12-11T03:48:00.000-08:00,endDate=2023-12-11T16:00:00.000-08:00,completeDate=2023-12-11T16:00:05.489-08:00,activatedDate=2023-12-11T15:56:42.006-08:00,sequence=5,goal=,autoStartStop=false]\"","authorAccountId":"5cdee6194326200dc9723dce","actor":{"type":"ACCOUNT_ID","value":"557058:f58131cb-b67d-43c7-b30d-6b58d40bd077"},"created":1704521545541,"updated":1704535957606,"trigger":{"id":"379623838","component":"TRIGGER","parentId":null,"conditionParentId":null,"schemaVersion":2,"type":"jira.issue.field.changed","value":{"changeType":"ANY_CHANGE","fields":[{"value":"Sprint","type":"fieldName"}],"actions":[]},"children":[],"conditions":[],"connectionId":null},"components":[{"id":"379623839","component":"ACTION","parentId":null,"conditionParentId":null,"schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702452982311","name":{"type":"FREE","value":"anchor"},"type":"SMART","query":{"type":"SMART","value":"0,"},"lazy":false},"children":[],"conditions":[],"connectionId":null},{"id":"379623840","component":"ACTION","parentId":null,"conditionParentId":null,"schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702449582115","name":{"type":"FREE","value":"fromList"},"type":"SMART","query":{"type":"SMART","value":"{{anchor.concat(fieldChange.from).split(',')}}"},"lazy":false},"children":[],"conditions":[],"connectionId":null},{"id":"379623841","component":"ACTION","parentId":null,"conditionParentId":null,"schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702465879402","name":{"type":"FREE","value":"fromListSize"},"type":"SMART","query":{"type":"SMART","value":"{{#=}}{{anchor.concat(fieldChange.from).split(',').size}}{{/}}"},"lazy":false},"children":[],"conditions":[],"connectionId":null},{"id":"379623842","component":"ACTION","parentId":null,"conditionParentId":null,"schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702372354065","name":{"type":"FREE","value":"fromListSum"},"type":"SMART","query":{"type":"SMART","value":"{{anchor.concat(fieldChange.from).split(',').sum.floor}}"},"lazy":false},"children":[],"conditions":[],"connectionId":null},{"id":"379623843","component":"ACTION","parentId":null,"conditionParentId":null,"schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702449665257","name":{"type":"FREE","value":"toList"},"type":"SMART","query":{"type":"SMART","value":"{{anchor.concat(fieldChange.to).split(',')}}"},"lazy":false},"children":[],"conditions":[],"connectionId":null},{"id":"379623844","component":"ACTION","parentId":null,"conditionParentId":null,"schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702465911403","name":{"type":"FREE","value":"toListSize"},"type":"SMART","query":{"type":"SMART","value":"{{#=}}{{anchor.concat(fieldChange.to).split(',').size}}{{/}}"},"lazy":false},"children":[],"conditions":[],"connectionId":null},{"id":"379623845","component":"ACTION","parentId":null,"conditionParentId":null,"schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702372391432","name":{"type":"FREE","value":"toListSum"},"type":"SMART","query":{"type":"SMART","value":"{{anchor.concat(fieldChange.to).split(',').sum.floor}}"},"lazy":false},"children":[],"conditions":[],"connectionId":null},{"id":"379623846","component":"ACTION","parentId":null,"conditionParentId":null,"schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702434584284","name":{"type":"FREE","value":"mergedSprintsString"},"type":"SMART","query":{"type":"SMART","value":"{{anchor.concat(fieldChange.from).concat(\",\").concat(anchor.concat(fieldChange.to)).remove(\" \")}}"},"lazy":false},"children":[],"conditions":[],"connectionId":null},{"id":"379623847","component":"ACTION","parentId":null,"conditionParentId":null,"schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702442284171","name":{"type":"FREE","value":"mergedSprintsListSum"},"type":"SMART","query":{"type":"SMART","value":"{{mergedSprintsString.split(',').distinct.sum}}"},"lazy":false},"children":[],"conditions":[],"connectionId":null},{"id":"379623848","component":"ACTION","parentId":null,"conditionParentId":null,"schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702455209130","name":{"type":"FREE","value":"previousSprintID"},"type":"SMART","query":{"type":"SMART","value":"{{#=}}{{mergedSprintsListSum}}-{{toListSum}}{{/}}"},"lazy":false},"children":[],"conditions":[],"connectionId":null},{"id":"379623849","component":"ACTION","parentId":null,"conditionParentId":null,"schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702455348543","name":{"type":"FREE","value":"currentSprintID"},"type":"SMART","query":{"type":"SMART","value":"{{#=}}{{mergedSprintsListSum}}-{{fromListSum}}{{/}}"},"lazy":false},"children":[],"conditions":[],"connectionId":null},{"id":"379623850","component":"ACTION","parentId":null,"conditionParentId":null,"schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702463652061","name":{"type":"FREE","value":"checkAdd"},"type":"SMART","query":{"type":"SMART","value":"{{#=}}{{toListSize}}-{{fromListSize}}{{/}}"},"lazy":false},"children":[],"conditions":[],"connectionId":null},{"id":"379623851","component":"ACTION","parentId":null,"conditionParentId":null,"schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702463716250","name":{"type":"FREE","value":"checkRemove"},"type":"SMART","query":{"type":"SMART","value":"{{#=}}{{fromListSize}}-{{toListSize}}{{/}}"},"lazy":false},"children":[],"conditions":[],"connectionId":null},{"id":"379623852","component":"BRANCH","parentId":null,"conditionParentId":null,"schemaVersion":1,"type":"jira.issue.related","value":{"relatedType":"current","jql":"","linkTypes":[],"onlyUpdatedIssues":false,"similarityLimit":40,"compareValue":0},"children":[{"id":"379623853","component":"CONDITION","parentId":"379623852","conditionParentId":null,"schemaVersion":1,"type":"jira.comparator.condition","value":{"first":"{{checkAdd}}","second":"-1","operator":"GREATER_THAN"},"children":[],"conditions":[],"connectionId":null},{"id":"379623854","component":"ACTION","parentId":"379623852","conditionParentId":null,"schemaVersion":1,"type":"jira.issue.outgoing.webhook","value":{"url":"https://jhnnym.atlassian.net/rest/agile/1.0/sprint/{{currentSprintID}}","headers":[{"id":"_header_1704525058207","name":"Authorization","value":"**************************","headerSecure":true}],"sendIssue":false,"contentType":"empty","customBody":null,"method":"GET","responseEnabled":true,"continueOnErrorEnabled":false},"children":[],"conditions":[],"connectionId":null},{"id":"379623855","component":"ACTION","parentId":"379623852","conditionParentId":null,"schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702251014615","name":{"type":"FREE","value":"currentSprintState"},"type":"SMART","query":{"type":"SMART","value":"{{webhookResponse.body.state}}"},"lazy":false},"children":[],"conditions":[],"connectionId":null},{"id":"379623856","component":"CONDITION","parentId":"379623852","conditionParentId":null,"schemaVersion":1,"type":"jira.comparator.condition","value":{"first":"{{currentSprintState}}","second":"active","operator":"EQUALS"},"children":[],"conditions":[],"connectionId":null},{"id":"379623857","component":"ACTION","parentId":"379623852","conditionParentId":null,"schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702469748807","name":{"type":"FREE","value":"sprintName"},"type":"SMART","query":{"type":"SMART","value":"{{webhookResponse.body.name}}"},"lazy":false},"children":[],"conditions":[],"connectionId":null},{"id":"379623858","component":"ACTION","parentId":"379623852","conditionParentId":null,"schemaVersion":1,"type":"jira.issue.outgoing.webhook","value":{"url":"https://webhook.site/c1df6916-2311-4fd6-a2e9-67cf3332aebe","headers":[{"id":"_header_1704535785066","name":"","value":"","headerSecure":false}],"sendIssue":false,"contentType":"custom","customBody":"{{now .convertToTimeZone(\"America/Los_Angeles\").longDateTime}}:\nAdded {{issue.key}} to active sprint '{{sprintName}}'\n\nOld Issue Sprint: '[{{fieldChange.fromString}}]'\nNew Issue Sprint: '[{{fieldChange.toString}}]'\n","method":"POST","responseEnabled":false,"continueOnErrorEnabled":false},"children":[],"conditions":[],"connectionId":null}],"conditions":[],"connectionId":null},{"id":"379623859","component":"CONDITION","parentId":null,"conditionParentId":null,"schemaVersion":1,"type":"jira.condition.container.block","value":null,"children":[{"id":"379623860","component":"CONDITION_BLOCK","parentId":"379623859","conditionParentId":null,"schemaVersion":1,"type":"jira.condition.if.block","value":{"conditionMatchType":"ALL"},"children":[{"id":"379623862","component":"ACTION","parentId":"379623860","conditionParentId":null,"schemaVersion":1,"type":"jira.issue.outgoing.webhook","value":{"url":"https://jhnnym.atlassian.net/rest/agile/1.0/sprint/{{previousSprintID}}","headers":[{"id":"_header_1704529322839","name":"Authorization","value":"**************************","headerSecure":true}],"sendIssue":false,"contentType":"empty","customBody":null,"method":"GET","responseEnabled":true,"continueOnErrorEnabled":false},"children":[],"conditions":[],"connectionId":null},{"id":"379623863","component":"ACTION","parentId":"379623860","conditionParentId":null,"schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1701947930023","name":{"type":"FREE","value":"previousSprintState"},"type":"SMART","query":{"type":"SMART","value":"{{webhookResponse.body.state}}"},"lazy":false},"children":[],"conditions":[],"connectionId":null},{"id":"379623864","component":"CONDITION","parentId":"379623860","conditionParentId":null,"schemaVersion":1,"type":"jira.comparator.condition","value":{"first":"{{previousSprintState}}","second":"active","operator":"EQUALS"},"children":[],"conditions":[],"connectionId":null},{"id":"379623865","component":"ACTION","parentId":"379623860","conditionParentId":null,"schemaVersion":1,"type":"jira.create.variable","value":{"id":"_customsmartvalue_id_1702469652306","name":{"type":"FREE","value":"sprintName"},"type":"SMART","query":{"type":"SMART","value":"{{webhookResponse.body.name}}"},"lazy":false},"children":[],"conditions":[],"connectionId":null},{"id":"379623866","component":"ACTION","parentId":"379623860","conditionParentId":null,"schemaVersion":1,"type":"jira.issue.outgoing.webhook","value":{"url":"https://webhook.site/c1df6916-2311-4fd6-a2e9-67cf3332aebe","headers":[{"id":"_header_1704535837538","name":"","value":"","headerSecure":false}],"sendIssue":false,"contentType":"custom","customBody":"{{now.convertToTimeZone(\"America/Los_Angeles\").longDateTime}}:\nRemoved issue {{issue.key}} from active sprint '{{sprintName}}'\n\nIssue Sprint: '[{{issue.sprint}}]'\nprevious sprint state: '{{previousSprintState}}'\n\nfieldChange.from : '{{fieldChange.fromString}}'\nfieldChange.to : '{{fieldChange.toString}}'\n","method":"POST","responseEnabled":false,"continueOnErrorEnabled":false},"children":[],"conditions":[],"connectionId":null}],"conditions":[{"id":"379623861","component":"CONDITION","parentId":null,"conditionParentId":"379623860","schemaVersion":1,"type":"jira.comparator.condition","value":{"first":"{{checkRemove}}","second":"-1","operator":"GREATER_THAN"},"children":[],"conditions":[],"connectionId":null}],"connectionId":null}],"conditions":[],"connectionId":null}],"canOtherRuleTrigger":false,"notifyOnError":"NEVER","projects":[],"labels":[],"tags":[{"id":54020255,"tagType":"IS_RULE_UPDATED","tagValue":"true"}],"ruleScope":{"resources":["ari:cloud:jira::site/d09e9e5a-a9d2-4a40-aa41-bd39061e4d35"]},"ruleHome":{"ruleLifecycleHome":{"locationARI":"ari:cloud:jira-software::site/d09e9e5a-a9d2-4a40-aa41-bd39061e4d35"},"ruleBillingHome":{"locationARI":"ari:cloud:jira-software::site/d09e9e5a-a9d2-4a40-aa41-bd39061e4d35"}},"writeAccessType":"UNRESTRICTED","collaborators":[],"billingType":"NORMAL"}]}

Updated on July 11, 2024

Still need help?

The Atlassian Community is here for you.