Is it possible to trigger a notification if a task or issue has no estimate? Edited

I have been tasked with developing a script that checks if a task or issue has no estimate. If the task does not have a estimate, it will trigger a notification to a specific user or via email (whatever is the best practice).

 

I have done research on the multiple components that go into developing this script but cannot get my head around how to implement and develop this.

I would preferably like to use this as an event listener for when a task is updated or created. Or if a workflow has been created or updated.

Could someone give me a starting point to work off and develop or possibly give me some better materials to look at than the ones that i currently have.

 

Many thanks

Tyler

3 answers

1 accepted

Hi Tyler,

you can achieve described functionality using Scriptrunner for JIRA Cloud. There are actually 2 ways that suits 2 slightly different usecases. 
- Scriptrunner provides Post function that you can add to your transitions to send notification in case some fields are not set. Have a look at the Send notification provided function. But that works only on transitions of an issue.

As i understood from your scenario, you want to send notification on each update/create of an issue.
- Create script listener as described in the documentation. Specify issue created and issue updated Events and in the code you can check the value of issue.fields.<name_of_field_you_want_to_check> and in case the condition is not met send notification using issue notify api call. Examples on how to make a call are here.

To figure out what fields are available for an issue and also to test your script use Script Console and here are examples.

Hope this helps, feel free to contact me for further info.

Regards,

Martin
Adaptavist

Hi Martin, 

 

Thank you for this reply, it helped me to understand the process behind the development of this script.

 

Currently i have wrote a prototype, but i am trying to access issue.fields.estimate (Also used .Estimate) and it is not working. Do you have any suggestions on why this is happening?

I was using the documentation on issues - https://confluence.atlassian.com/adminjiracloud/issue-fields-and-statuses-776636356.html 

 

This states that Estimate is a valid identifier for issue.fields.

 

my code is below

 

import groovy.xml.MarkupBuilder



if (issue.fields.estimate == null) {
def writer = new StringWriter()
def markupBuilder = new MarkupBuilder(writer)
markupBuilder.div {
p {
a(href: "https://b13technology.atlassian.net/issue/${issue.key}", issue.key)
span("This issue does not have an Estimate")
}
}

def htmlMessage = writer.toString()
def textMessage = new XmlSlurper().parseText(htmlMessage).text()

def resp = post("/rest/api/2/issue/${issue.id}/notify")
.header("Content-Type", "application/json")
.body([
subject: '${issue.id} has no Estimate',
textBody: textMessage,
htmlBody: htmlMessage,
to: [
groups: [[
name: 'site-admins',
]]
]
])

}

Hi Tyler,

the best way to figure out the name of your custom field in general is to use Script Console and run script like this one to list all the fields :

def issueKey = 'TEST-1'

def result = get('/rest/api/2/issue/' + issueKey)
.header('Content-Type', 'application/json')
.asObject(Map)
if (result.status == 200) {
result.body.fields
} else {
"Failed"
}
I think the field you are looking for is called originalEstimate and if it exists you should be able to access it 
issue.fields?.timetracking?.originalEstimate

 Regards,

Martin

Hi Martin,

Thank you again for your continued support.

This has solved the issue i was having accessing the specified field, it has also solved potential blockers i may run in to in the near future. 

One last issue i am having is with the XMLMarkup i am carrying out.

the error i am getting is the following:

 err.png

I was also using this as a reference:

 

http://docs.groovy-lang.org/latest/html/documentation/#_markupbuilder

 

Hope you are able to help and once again, Thank you.

Many thanks

Tyler

Hi Tyler,

please have a look at the example the comment there is the following

def writer = new StringWriter() 
// Note that markup builder will result in static type errors as it is dynamically typed.
// These can be safely ignored
def markupBuilder = new MarkupBuilder(writer)

The static code checking does not work on 100% and it can only determine types of objects where it knows the type. 

Hope it will work for you.

Regards,

Martin

Hi Martin,

Thank you for the help.

I did see that comment on a few of the examples you provided.

The issue i am getting is once the event listener is triggered is the following:

 

Processing webhook event from JIRA Cloud failed, please find below details:
You can find more details about this error on Diagnostics & Settings page.
CorrelationId: 588782f0-01e8-42c7-a305-dbfa88b84d91
Issue id: 38038
Affected scripts: adf11da0-0655-4ab6-85c3-986a80cd6999
Payload:
",
"name" : "Major",
"id" : "3"
},
"customfield_10300" : null,
"labels" : [ ],
"customfield_10016" : null,
"customfield_10017" : null,
"customfield_10018" : null,
"customfield_10019" : null,
"timeestimate" : null,
"aggregatetimeoriginalestimate" : null,
"versions" : [ ],
"issuelinks" : [ ],
"assignee" : null,
"updated" : "2017-12-06T19:43:00.633+0500",
"status" : {
"self" : "https://testing.atlassian.net/rest/api/2/status/10001",
"description" : "",
"iconUrl" : "https://testing.atlassian.net/images/icons/statuses/open.png",
"name" : "To Do",
"id" : "10001",
"statusCategory" : {
"self" : "https://testing.atlassian.net/rest/api/2/statuscategory/2",
"id" : 2,
"key" : "new",
"colorName" : "blue-gray",
"name" : "To Do"
}
},
"components" : [ ],
"timeoriginalestimate" : null,
"description" : null,
"customfield_11023" : null,
"customfield_10011" : "0|r90x3v:",
"customfield_11024" : null,
"customfield_10012" : null,
"customfield_11025" : null,
"customfield_10013" : null,
"customfield_10014" : null,
"customfield_11026" : null,
"timetracking" : { },
"customfield_11027" : null,
"customfield_10015" : null,
"customfield_10006" : [ ],
"customfield_10600" : "{}",
"customfield_10007" : null,
"security" : null,
"customfield_10800" : null,
"aggregatetimeestimate" : null,
"attachment" : [ ],
"summary" : "testing notification send for task with no estimate",
"creator" : {
"self" : "https://testing.atlassian.net/rest/api/2/user?username=tyler",
"name" : "tyler",
"key" : "tyler",
"accountId" : "557058:7254dd18-3ac3-4675-a22e-a4bf1a7963f4",
"emailAddress" : "tyler@testing.com",
"avatarUrls" : {
"48x48" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=48&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D48%26noRedirect%3Dtrue",
"24x24" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=24&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D24%26noRedirect%3Dtrue",
"16x16" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=16&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D16%26noRedirect%3Dtrue",
"32x32" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D32%26noRedirect%3Dtrue"
},
"displayName" : "Tyler Brown-Jones",
"active" : true,
"timeZone" : "UK"
},
"subtasks" : [ ],
"reporter" : {
"self" : "https://testing.atlassian.net/rest/api/2/user?username=tyler",
"name" : "tyler",
"key" : "tyler",
"accountId" : "557058:7254dd18-3ac3-4675-a22e-a4bf1a7963f4",
"emailAddress" : "tyler@testing.com",
"avatarUrls" : {
"48x48" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=48&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D48%26noRedirect%3Dtrue",
"24x24" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=24&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D24%26noRedirect%3Dtrue",
"16x16" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=16&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D16%26noRedirect%3Dtrue",
"32x32" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D32%26noRedirect%3Dtrue"
},
"displayName" : "Tyler Brown-Jones",
"active" : true,
"timeZone" : "UK"
},
"aggregateprogress" : {
"progress" : 0,
"total" : 0
},
"customfield_10000" : null,
"customfield_10001" : null,
"customfield_10002" : null,
"customfield_10200" : null,
"customfield_10003" : null,
"customfield_10201" : null,
"customfield_10400" : null,
"environment" : null,
"duedate" : null,
"progress" : {
"progress" : 0,
"total" : 0
},
"comment" : {
"comments" : [ {
"self" : "https://testing.atlassian.net/rest/api/2/issue/38038/comment/30191",
"id" : "30191",
"author" : {
"self" : "https://testing.atlassian.net/rest/api/2/user?username=tyler",
"name" : "tyler",
"key" : "tyler",
"accountId" : "557058:7254dd18-3ac3-4675-a22e-a4bf1a7963f4",
"emailAddress" : "******",
"avatarUrls" : {
"48x48" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=48&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D48%26noRedirect%3Dtrue",
"24x24" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=24&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D24%26noRedirect%3Dtrue",
"16x16" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=16&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D16%26noRedirect%3Dtrue",
"32x32" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D32%26noRedirect%3Dtrue"
},
"displayName" : "Tyler Brown-Jones",
"active" : true,
"timeZone" : "UK"
},
"body" : "test",
"updateAuthor" : {
"self" : "https://testing.atlassian.net/rest/api/2/user?username=tyler",
"name" : "tyler",
"key" : "tyler",
"accountId" : "557058:7254dd18-3ac3-4675-a22e-a4bf1a7963f4",
"emailAddress" : "tyler@testing.com",
"avatarUrls" : {
"48x48" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=48&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D48%26noRedirect%3Dtrue",
"24x24" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=24&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%

 

I hope you can help

 

Kindest regards 

Tyler. 

Hi Martin,

Thank you for the help.

 

I did notice that comment on a few of the examples.

I am now getting an error once the Event Listener is triggered:

Processing webhook event from JIRA Cloud failed, please find below details:
You can find more details about this error on Diagnostics & Settings page.
CorrelationId: 588782f0-01e8-42c7-a305-dbfa88b84d91
Issue id: 38038
Affected scripts: adf11da0-0655-4ab6-85c3-986a80cd6999
Payload:
",
"name" : "Major",
"id" : "3"
},
"customfield_10300" : null,
"labels" : [ ],
"customfield_10016" : null,
"customfield_10017" : null,
"customfield_10018" : null,
"customfield_10019" : null,
"timeestimate" : null,
"aggregatetimeoriginalestimate" : null,
"versions" : [ ],
"issuelinks" : [ ],
"assignee" : null,
"updated" : "2017-12-06T19:43:00.633+0500",
"status" : {
"self" : "https://testing.atlassian.net/rest/api/2/status/10001",
"description" : "",
"iconUrl" : "https://testing.atlassian.net/images/icons/statuses/open.png",
"name" : "To Do",
"id" : "10001",
"statusCategory" : {
"self" : "https://testing.atlassian.net/rest/api/2/statuscategory/2",
"id" : 2,
"key" : "new",
"colorName" : "blue-gray",
"name" : "To Do"
}
},
"components" : [ ],
"timeoriginalestimate" : null,
"description" : null,
"customfield_11023" : null,
"customfield_10011" : "0|r90x3v:",
"customfield_11024" : null,
"customfield_10012" : null,
"customfield_11025" : null,
"customfield_10013" : null,
"customfield_10014" : null,
"customfield_11026" : null,
"timetracking" : { },
"customfield_11027" : null,
"customfield_10015" : null,
"customfield_10006" : [ ],
"customfield_10600" : "{}",
"customfield_10007" : null,
"security" : null,
"customfield_10800" : null,
"aggregatetimeestimate" : null,
"attachment" : [ ],
"summary" : "testing notification send for task with no estimate",
"creator" : {
"self" : "https://testing.atlassian.net/rest/api/2/user?username=tyler",
"name" : "tyler",
"key" : "tyler",
"accountId" : "557058:7254dd18-3ac3-4675-a22e-a4bf1a7963f4",
"emailAddress" : "tyler@testing.com",
"avatarUrls" : {
"48x48" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=48&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D48%26noRedirect%3Dtrue",
"24x24" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=24&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D24%26noRedirect%3Dtrue",
"16x16" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=16&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D16%26noRedirect%3Dtrue",
"32x32" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D32%26noRedirect%3Dtrue"
},
"displayName" : "Tyler Brown-Jones",
"active" : true,
"timeZone" : "UK"
},
"subtasks" : [ ],
"reporter" : {
"self" : "https://testing.atlassian.net/rest/api/2/user?username=tyler",
"name" : "tyler",
"key" : "tyler",
"accountId" : "557058:7254dd18-3ac3-4675-a22e-a4bf1a7963f4",
"emailAddress" : "tyler@testing.com",
"avatarUrls" : {
"48x48" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=48&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D48%26noRedirect%3Dtrue",
"24x24" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=24&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D24%26noRedirect%3Dtrue",
"16x16" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=16&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D16%26noRedirect%3Dtrue",
"32x32" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D32%26noRedirect%3Dtrue"
},
"displayName" : "Tyler Brown-Jones",
"active" : true,
"timeZone" : "UK"
},
"aggregateprogress" : {
"progress" : 0,
"total" : 0
},
"customfield_10000" : null,
"customfield_10001" : null,
"customfield_10002" : null,
"customfield_10200" : null,
"customfield_10003" : null,
"customfield_10201" : null,
"customfield_10400" : null,
"environment" : null,
"duedate" : null,
"progress" : {
"progress" : 0,
"total" : 0
},
"comment" : {
"comments" : [ {
"self" : "https://testing.atlassian.net/rest/api/2/issue/38038/comment/30191",
"id" : "30191",
"author" : {
"self" : "https://testing.atlassian.net/rest/api/2/user?username=tyler",
"name" : "tyler",
"key" : "tyler",
"accountId" : "557058:7254dd18-3ac3-4675-a22e-a4bf1a7963f4",
"emailAddress" : "******",
"avatarUrls" : {
"48x48" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=48&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D48%26noRedirect%3Dtrue",
"24x24" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=24&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D24%26noRedirect%3Dtrue",
"16x16" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=16&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D16%26noRedirect%3Dtrue",
"32x32" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D32%26noRedirect%3Dtrue"
},
"displayName" : "Tyler Brown-Jones",
"active" : true,
"timeZone" : "UK"
},
"body" : "test",
"updateAuthor" : {
"self" : "https://testing.atlassian.net/rest/api/2/user?username=tyler",
"name" : "tyler",
"key" : "tyler",
"accountId" : "557058:7254dd18-3ac3-4675-a22e-a4bf1a7963f4",
"emailAddress" : "tyler@testing.com",
"avatarUrls" : {
"48x48" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=48&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%3Dmm%26s%3D48%26noRedirect%3Dtrue",
"24x24" : "https://avatar-cdn.atlassian.com/c47376834fa97456a81828b213fe20d3?s=24&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fc47376834fa97456a81828b213fe20d3%3Fd%

I hope you can help resolve this error.

 

Kindest regards,

Tyler.

Hi Martin

Thank you for the help.

I notice that error on a few of the examples and took it into account.

After testing, i come across this error Error over email - link to pastebin

 

I hope you can help

 

Many thanks

Tyler

Apologies for the numerous posts, it did not load the first two in until 10 minutes later.

Hi,

use attached script, fixed few small things there.

 

import groovy.xml.MarkupBuilder
if (issue.fields?.timetracking?.originalEstimate == null) {
def writer = new StringWriter()
def markupBuilder = new MarkupBuilder(writer)
markupBuilder.div {
p {
a(href: "https://b13technology.atlassian.net/issue/${issue.key}", issue.key)
span("This issue does not have an Estimate")
}
}

def htmlMessage = writer.toString()
def textMessage = new XmlSlurper().parseText(htmlMessage).text()

def resp = post("/rest/api/2/issue/${issue.id}/notify")
.header("Content-Type", "application/json")
.body([
subject: "${issue.id} has no Estimate",
textBody: textMessage,
htmlBody: htmlMessage,
to: [
reporter: issue.fields.reporter != null, // bug - 500 error when no reporter
assignee: issue.fields.assignee != null, // bug - 500 error when no assignee
groups: [[
name: 'site-admins',
]]
]
]).asString()
logger.info(resp.toString())
assert resp.status == 204

}

Hi Martin

 

Thank you for all of your help and support, i now know for future reference what i did wrong and what i can improve on.

Kindest regards

Tyler.

@Tyler Brown-Jones

If you're looking for a way to trigger email when issue has no estimate assigned then in my view it is best to have a periodical email digest of these issues grouped by issue assignee. Our add-on Jirassimo notifications can help you out with that. 

Cheers,

Vlad

0 votes

Hi Tyler,

You are using ScriptRunner for JIRA (Server), correct?

There's several ways to accomplish this. I think the easiest solution, as you alluded to already, is to develop a listener that sends out an email whenever an issue of type "Task" is created or updated and has an empty value for the Estimate. I can help you with that.

Though I should probably ask: why not just prevent this kind of behaviour in the first place? Why not force the user to enter an Estimate whenever they create or edit an issue? I can definitely understand why you would not want to do this, but I figured I might ask anyway.

Regards,

Josh

Hi Joshua - thank you for your reply

Apologies for a delayed reply, i have been out of office.

We are currently using ScriptRunner for JIRA Cloud.

The option in your first paragraph would have to be the option we go for, this is because the developers are not the only user adding issues and tasks. QA's and testers also add these issues and tasks too. 

If you could help me or give me some guidance on this, it would be greatly appreciated.

Many thanks,

Tyler.

Hi Tyler,

Unfortunately I do not have any experience with JIRA Cloud. ScriptRunner for JIRA Cloud is totally different than ScriptRunner for JIRA Server.

Let me see if I can get a colleague to look at your question.

Regards,

Josh

Suggest an answer

Log in or Sign up to answer
Community showcase
Posted Oct 11, 2018 in Marketplace Apps

You + one app + a desert island...

Hi all! My name is Miles and I work on the Marketplace team. We’re looking for better ways to recommend and suggest apps that are truly crowd favorites, so of course we wanted to poll the Community. ...

2,693 views 5 6
Join discussion

Atlassian User Groups

Connect with like-minded Atlassian users at free events near you!

Find a group

Connect with like-minded Atlassian users at free events near you!

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you