Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

Remove watchers when creating clone via workflow post function (scriptrunner)

Becky Simpkins March 5, 2018

I've built a workflow that has a transition from Closed to Closed called 'Clone' that creates a clone of the ticket into a different project and as a different issue type.  I'm accomplishing this through a ScriptRunner post function, 'Clones an issue and links'.  (In case it becomes important, it is currently the first post function in that transition.)  Within the clone post function, I've set the new target project and target issue type.  All gravy.  ScriptRunner is the best.

Here is where I need help.  

In the 'Additional issue actions' of that post function I want to replace the clone's Watcher field with users from a custom user-picker field (multi user field, called "Team").  This is important for us because there is often a dozen or more watchers on the original ticket whereas the clone will only have 2-3 watchers.  And those populations don't overlap. 

I don't know groovy, but I've used this community forum and lots of testing to hobble together enough so that this post function already (a) strips attachments, (b) gives the clone a name based on the original ticket, and (c) sets the clone's assignee based on a custom field ("Manager").  

Any ideas on how to replace the Watchers field with information from the "Team" custom user-picker field?  Thanks for any and all help!

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.UpdateIssueRequest

// get required Managers
def customFieldManager = ComponentAccessor.getCustomFieldManager()

// rename clone Summary field
issue.setSummary("Case" + " - " + issue.getSummary())

// remove attachments
checkAttachment = {attachment -> false}

// get a pointer to the user picker field and its value
def userCf = customFieldManager.getCustomFieldObjectByName("Manager")
def implUser = issue.getCustomFieldValue(userCf) as ApplicationUser

// if the user picker field is not null then set the assignee
if(implUser){
issue.setAssigneeId(implUser.username.toString())
}

 

 

1 answer

Suggest an answer

Log in or Sign up to answer
0 votes
Joshua Yamdogo @ Adaptavist
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 12, 2018

Hi Becky,

Something like this should work:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.UpdateIssueRequest

// get required Managers
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def watcherManager = ComponentAccessor.getWatcherManager()
def groupManager = ComponentAccessor.getGroupManager()
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
def locale = ComponentAccessor.getLocaleManager().getLocaleFor(user)

// rename clone Summary field
issue.setSummary("Case" + " - " + issue.getSummary())

// remove attachments
checkAttachment = {attachment -> false}

// get a pointer to the user picker field and its value
def userCf = customFieldManager.getCustomFieldObjectByName("Manager")
def implUser = issue.getCustomFieldValue(userCf) as ApplicationUser

// if the user picker field is not null then set the assignee
if(implUser){
issue.setAssigneeId(implUser.username.toString())
}

// Remove all watchers from issue
def watchers = watcherManager.getWatchers(issue, locale)
watchers.each { watcher ->
watcherManager.stopWatching(watcher, issue)
}

// Add all users from Team group as watchers
def teamGroup = groupManager.getGroup("Team")
teamGroup.each { teamMember ->
watcherManager.startWatching(teamMember, issue)
}
Becky Simpkins March 13, 2018

Thank you for responding!  I used the script above.  In the 'Additional issue actions' it is flagging this piece: 

watcherManager.startWatching(teamMember, issue)

saying: 

Cannot find the matching method com.atlassian.jira.issue.watchers.WatcherManager#startWatching(java.lang.Object,com.atlassian.jira.issue.MutableIssue). Please check if the declared type is right an if the method exists.

I went ahead and ran a ticket through the workflow to get a log:

2018-03-13 10:27:09,681 ERROR [workflow.ScriptWorkflowFunction]: *************************************************************************************
2018-03-13 10:27:09,690 ERROR [workflow.ScriptWorkflowFunction]: Script function failed on issue: OGC-1175, actionId: 41, file: null
java.lang.NullPointerException
 at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:210)
 at com.google.common.cache.LocalCache.get(LocalCache.java:3936)
 at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3941)
 at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4824)
 at com.google.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:4830)
 at com.atlassian.jira.issue.watchers.DefaultWatcherManager.getWatcherUserKeys(DefaultWatcherManager.java:150)
 at com.atlassian.jira.issue.watchers.DefaultWatcherManager.getWatchers(DefaultWatcherManager.java:136)
 at com.atlassian.jira.issue.watchers.WatcherManager$getWatchers.call(Unknown Source)
 at Script822.run(Script822.groovy:30)

 Do you see the issue?   

Joshua Yamdogo @ Adaptavist
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 13, 2018

Hi Becky, 

There was a small error in the code. It should have been groupManager.getUsersInGroup

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.user.ApplicationUser

// get required Managers
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def watcherManager = ComponentAccessor.getWatcherManager()
def groupManager = ComponentAccessor.getGroupManager()
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
def locale = ComponentAccessor.getLocaleManager().getLocaleFor(user)

// rename clone Summary field
issue.setSummary("Case" + " - " + issue.getSummary())

// remove attachments
//checkAttachment = {attachment -> false}

// get a pointer to the user picker field and its value
def userCf = customFieldManager.getCustomFieldObjectByName("Manager")
def implUser = issue.getCustomFieldValue(userCf) as ApplicationUser

// if the user picker field is not null then set the assignee
if(implUser){
issue.setAssigneeId(implUser.username.toString())
}

// Remove all watchers from issue
def watchers = watcherManager.getWatchers(issue, locale)
watchers.each { watcher ->
watcherManager.stopWatching(watcher, issue)
}

// Add all users from Team group as watchers
def teamGroup = groupManager.getUsersInGroup("Team")
teamGroup.each { teamMember ->
watcherManager.startWatching(teamMember, issue)
}

I tested it in my instance and it seems to work now with new watchers added to my cloned issue:

Screen Shot 2018-03-13 at 12.53.46 PM.png

Becky Simpkins March 15, 2018

It's strange -- the post function is still not working in my instance.  I'm getting the same log error as before. 

It seems to be this part that is causing the error.  Do you have an idea why this is failing?

// Remove all watchers from issue
def watchers = watcherManager.getWatchers(issue, locale)
watchers.each { watcher ->
watcherManager.stopWatching(watcher, issue)
}

 Thanks very much for your help with this.  

Joshua Yamdogo @ Adaptavist
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 19, 2018

Hi Becky,

Which version of ScriptRunner are you running? You can find it on the manage add-ons page in JIRA.

Thanks,

Josh

Becky Simpkins March 20, 2018

Hi Josh,  We're running version 4.3.15

Thanos Batagiannis _Adaptavist_
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 20, 2018

Hi Becky,

In that case you have to make use of the doAfterCreate callback (closure)

So in your case will be something like 

doAfterCreate = {
def watchers = watcherManager.getWatchers(issue, locale)
watchers.each { watcher ->
watcherManager.stopWatching(watcher, issue)
}
}

Let us know if that worked for you.  

Becky Simpkins March 20, 2018

Many thanks, Thanos. I tried the doAfterCreate suggestion.  No luck.  The clone is created but the Watcher field is not wiped.  No error log reported.  I also tried moving the post-function that's creating the clone to be the last post-function -- it had been the first.  No luck there either.

Let me know if there is anything I can try to help troubleshoot. 

Here is the full script:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.UpdateIssueRequest

// get required Managers
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def watcherManager = ComponentAccessor.getWatcherManager()
def groupManager = ComponentAccessor.getGroupManager()
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
def locale = ComponentAccessor.getLocaleManager().getLocaleFor(user)

// rename clone Summary field
issue.setSummary("Case" + " - " + issue.getSummary())

// remove attachments
checkAttachment = {attachment -> false}

// get a pointer to the user picker field and its value
def userCf = customFieldManager.getCustomFieldObjectByName("Manager")
def implUser = issue.getCustomFieldValue(userCf) as ApplicationUser

// if the user picker field is not null then set the assignee
if(implUser){
issue.setAssigneeId(implUser.username.toString())
}

// remove all watchers of clone
doAfterCreate = {
def watchers = watcherManager.getWatchers(issue, locale)
watchers.each { watcher ->
watcherManager.stopWatching(watcher, issue)
}
}

Also, do you think a listener be better?  I haven't created a listener before but know that they can modify tickets.  If so, would I use your doAfterCreate script suggestion above or do listeners require different scripting?

Thanos Batagiannis _Adaptavist_
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 20, 2018

Hey Becky, 

This should have worked ,

import com.atlassian.jira.component.ComponentAccessor

doAfterCreate = {
ComponentAccessor.watcherManager.getWatchersUnsorted(issue)?.each {
ComponentAccessor.watcherManager.stopWatching(it, issue)
}
}

Can I ask you where is your post function ? Which step and in what order ?

Also can you please check your application logs for any errors ? 

Becky Simpkins March 20, 2018

It is the first post function in a transition called 'Clone' that goes from Closed back to Closed.  The idea is that after a ticket is closed, you press a button and make a clone into a new Project / Issue Type.  Attaching a screenshot of the post function ordering and the workflow.  

Capture.PNG

Capture2.PNG

I'll ask another one of our admins for the application logs. 

Static checking on the script above says it cannot find the matching method for the ComponentAccessor lines.  When I pushed a ticket through the transition to see what would happen, it provided this log:

2018-03-20 16:02:16,787 ERROR [workflow.ScriptWorkflowFunction]: *************************************************************************************
2018-03-20 16:02:16,787 ERROR [workflow.ScriptWorkflowFunction]: Script function failed on issue: OGC-1175, actionId: 41, file: null
groovy.lang.MissingMethodException: No signature of method: com.atlassian.jira.issue.watchers.DefaultWatcherManager.getWatchersUnsorted() is applicable for argument types: (com.atlassian.jira.issue.IssueImpl) values: [BMS-133]
 at Script944$_run_closure2.doCall(Script944.groovy:31)
 at Script944$_run_closure2.doCall(Script944.groovy)
 at com.onresolve.scriptrunner.canned.jira.utils.AbstractCloneIssue.doScript(AbstractCloneIssue.groovy:125)
 at com.onresolve.scriptrunner.canned.jira.utils.CopyIssueWithAttachments.super$2$doScript(CopyIssueWithAttachments.groovy)
 at com.onresolve.scriptrunner.canned.jira.utils.CopyIssueWithAttachments.doScript(CopyIssueWithAttachments.groovy:13)
 at com.onresolve.scriptrunner.canned.jira.workflow.postfunctions.CloneIssue.super$3$doScript(CloneIssue.groovy)
 at com.onresolve.scriptrunner.canned.jira.workflow.postfunctions.CloneIssue.doScript(CloneIssue.groovy:89)
Davin Studer
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 21, 2019

I had the same issue that it would not clear the watchers on creation of the issue. This is how I solved it.

https://community.atlassian.com/t5/Jira-questions/Use-ScriptRunner-to-un-watch-an-issue-when-created/qaq-p/1038959#U1039042

TAGS
AUG Leaders

Atlassian Community Events