Scriptrunner Set/Clear Resolutions Globally

Timothy Ryner July 1, 2022

Seek assistance writing a Scriptrunner script that sets/clears the Resolution globally based on Status Category, without using Post Functions

  • When an issue is transitioned (any issue in the instance, in any project)
    • If Status Category is in "To Do" or "In Progress"
      • Resolution is cleared, set to "None" (empty). 
    • If Status Category is in "Done"
      • the Resolution is set to "Done".

+ Also, have the ability to limit the script to certain projects initially for testing, before enabling globally.

++ We have the Automation plugin, which is a good candidate for simply executing the script on the Issue Transitioned event, and also allows for project-level implementation.

 

import com.atlassian.jira.util.ImportUtils
import com.atlassian.jira.issue.index.IssueIndexingService
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.component.ComponentAccessor

def is = ComponentAccessor.issueService
def iip =is.newIssueInputParameters()
iip.setSkipScreenCheck(true) //only need this if the resolution is not editable
//iip.resolutionId = null
iip.resolutionId = issue.status.statusCategory.primaryAlias == 'Done' ? '10000' : null

def result = is.validateUpdate(currentUser, issue.id, iip)
assert result.valid : result.errorCollection.errors
def updatedIssue = is.update(currentUser, result, EventDispatchOption.DO_NOT_DISPATCH, false).issue

//updatedIssue.resolutionDate = new Date().toTimestamp()
//issue.store()
//update the JIRA index so that jql  for "resolved" work
//boolean wasIndexing = ImportUtils.isIndexIssues()
//ImportUtils.setIndexIssues(true)
//ComponentAccessor.getComponent(IssueIndexingService.class).reIndex(updatedIssue)
//ImportUtils.setIndexIssues(wasIndexing)

 

Rationale:  Our small team manages multiple large Jira instances with thousands of projects, all managed by our Users/Project Admins (and not by the Jira Admins).  The instances have been deliberately configured to give the Users and Project Admins as many project configuration options as possible without needing a Jira Admin.  Overall, we have been very successful.  Resolutions are one of our last pinch points.

Project Admins cannot manage their own Resolutions reliably without a Jira Admin needing to configure Transition Screens and Post Functions.  We've worked on multiple potential solutions (user training to use Simplified Workflows, Project Automation), but still, Jira Admins are the bottleneck for Resolutions.  

So we've decided that the Resolution should be set globally for all issues based on the Status Category.  This way, Project Admins can passively self administer their Resolution by only using "Done" statuses when they want the Resolution to be set.

Any help configuring this functionality is greatly appreciated!  If I need to go it alone, so be it.  I'll post the code here for others to use.

 

3 answers

1 accepted

1 vote
Answer accepted
Timothy Ryner August 11, 2022

Final Update:

I was able to put together an Automation Rule/Scriptrunner Script combo that will edit the Resolution & Resolved date based on the Status Category.

I leveraged more of the Rule Conditions to make the scripts as simple as possible, since I'm not Scriptrunner savvy and don't want to create something I can't fix.  The scripts will probably evolve over time, but for now, it does what it needs to do.

 


Automation Rule Configurations:

  • Event:  Issue Transitioned
    • Condition:  (none)  
      • Action:  Execute Script
        Sets Resolution based on Status Category
        • Status Category = To Do, In Progress
          Resolution = None (null)
        • Status Category = Done
          Resolution = Done
  • Then, if:
    • Condition:  Status Category = To Do, In Progress
      • Action:  Execute Script
        • Set Resolved date = None (null)
  • Else if:
    • Condition:  Status Category = To Do, In Progress
      • Action:  Execute Script
        • Set Resolved date = Now

Set Resolution Rule Breakdown.PNG

Set Resolution Script:

import com.atlassian.jira.util.ImportUtils
import com.atlassian.jira.issue.index.IssueIndexingService
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.component.ComponentAccessor
import java.sql.Timestamp
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.MutableIssue

def is = ComponentAccessor.issueService
def iip =is.newIssueInputParameters()

iip.setSkipScreenCheck(true) //only need this if the resolution is not editable
iip.resolutionId = issue.status.statusCategory.primaryAlias == 'Done' ? '10000' : null

def result = is.validateUpdate(currentUser, issue.id, iip)
assert result.valid : result.errorCollection.errors

def updatedIssue = is.update(currentUser, result, EventDispatchOption.DO_NOT_DISPATCH, false).issue
Set Resolved date to Now Script
import java.sql.Timestamp
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.MutableIssue

def issueMutable = issue as MutableIssue
def issueManager = ComponentAccessor.issueManager
def issueService = ComponentAccessor.issueService
def loggedInUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser

issueMutable.setResolutionDate(new Timestamp(System.currentTimeMillis()))

issueMutable.store()

 

Set Resolved date to Null Script

import java.sql.Timestamp
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.MutableIssue

def issueMutable = issue as MutableIssue
def issueManager = ComponentAccessor.issueManager
def issueService = ComponentAccessor.issueService
def loggedInUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser

issueMutable.setResolutionDate(null)

issueMutable.store()
Hopefully this is helpful to others seeking to escape the administrative tyranny of Resolution configurations.
Sarah Kladstrup December 5, 2022

Script Runner is giving me a warning about the issueMutable.store() line:

  • Use the Object's Service or Manager to save values. Since v5.0. DO NOT USE THIS as it overwrites all the fields of the issue which can result in difficult to reproduce bugs Prefer to use QueryDslAccessor to change only needed fields

Any suggestions?

Timothy Ryner December 6, 2022

Can you re-ask this question in the other thread (link below)? 

I only posted the outcome here for some extra reach.  It'll be the better place to document the follow-on questions.

Solved: Scriptrunner w/ Automation - Set Resolution (atlassian.com)

I have several new things to post, once you ask. :)

0 votes
Timothy Ryner November 7, 2022

Three months later, and I can say that this has been wildly successful. 

The auto-resolution script runs around 7000 times a day, happily setting/clearing the Resolution & Resolved date.  I created a new field "Outcome", populated it with the same field options as Resolution, copied over the values globally, and placed it on the transition screens in place of Resolution. 

  • No customers are throwing a fit.  If you didn't know better, the system now functions how you'd think it would, and wouldn't suspect that it's a customization.
  • It passively fixed dozens of project workflows that were missing the post-function configurations to set the Resolution.  So instead of having thousands of issues with missing Resolutions, they're always set, regardless of how many configuration changes the Project Admins make to their workflows.
  • Customers can still capture data granularity with the "Outcome" field, just as they could before with Resolution (and with more options, because Project Admins can edit their field options).
  • Significant time has been freed up for the Admin Team not having to reconfigure workflows or teaching people about Simplified Workflows.
0 votes
Clark Everson
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
July 1, 2022

Hi @Timothy Ryner 

I would advise against this. One major benefit of resolutions is it tells you why an issue is done and shows up in reporting. Where as if you try to differentiate issues based off their status this won't show up in reporting.

Having the Done status and then having only one resolution from a scalable agile standpoint will provide false data. The resolution provides the ability to also be done via screens and then allows user to select why it's done, like duplicate issues, things that won't be done etc. 

By skipping this you are missing out on major features of jira and will really hinder users as the tool is scaled

From a UI standpoint yes it's easier but the data will not always be accurate and there is nothing worse than false data in a system.

Best,
Clark

Timothy Ryner July 5, 2022

@Clark Everson 

Completely understand this compromise.  I'm a highly-experienced Jira Admin.  Resolutions have many benefits for instances that have tighter control on workflow & project configurations.   But that is not our delivery model.  Our users get projects created automatically, and they get full permissions to edit workflows.  So they very quickly (1) break the Simplified Workflow feature inside of Boards, and (2) break the workflow post-function & transition screen Resolution configs by removing/editing transitions.  So having the Resolution set automatically & globally would be a desirable behavior.   

Want to talk about False Data?  I've pulled the data for Resolutions:

  • Fewer than 1% of issues that have a Resolution are set to something different than "Done". 
  • However, 20% of issues have a status of Done but no Resolution. 

And this is with us spending several hours a week trying to configure projects with post-functions and transition screens.  So we do have a False Data problem, mostly stemming from the Resolution not being set.  Setting globally fixes tens of thousands of issues, while sacrificing granularity on a thousand (which we've implemented a workaround to capture anyway).  

Want to talk about missing out on the features of Jira?  Atlassian makes "Simplified Workflows" so users can automatically set the Resolution to Done.  So Atlassian recognizes that setting all issues to Done gives a majority of the desired functionality.  

Clearly in our instance, most of our users would prefer the automatic setting, and our Jira Admin team (2 people) will gain many hours per week back.  

If you know a way to configure this, I'm all ears. 

Clark Everson
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
July 14, 2022

@Timothy Ryner 

You are correct atlassian does have simplified workflows. However depending on the size of the instance it isn't always recommended to allow them in your instance. 

Looking back on Jira history: https://community.atlassian.com/t5/Jira-questions/Resolution-automatically-set-to-Fixed-once-a-Custom-field-is/qaq-p/874085

May solve your issue.

But I would still weigh the risks. If your instance is a large instance I would suggest standardizing the workflows. i do see you are still on a server instance. in two years server is being deprecated.

Regardless if you go data center or cloud, there will be roadmap functionality you may not currently have. From experience, using the roadmap functionality is something many users will ask for, however it, on a company portfolio level it is near impossible to implement if there are not core sets of workflows/statuses etc, and potentially removing the simplified workflow options. My company is very large and we've been already working on this for 3 years, so if you are still in the planning stages for cloud or data center make sure to think about those other functionality you will be gaining from your migration as well. It's much easier to set yourself up starting now for success then needing to back track in a couple years.

Best,
Clark

Timothy Ryner July 15, 2022

It doesn't sound like you've got Scriptrunner chops that will further my mission.  But what the hell, I'll debate anyway without an expectation of a Scriptrunner outcome.

Yes, I'm aware of ALL of that.  Our delivery model is such that the instance is not tightly controlled, because there is tremendous value in allowing our end users to customize their projects to fit their needs.  In a way, we made Server act like Data Center & Cloud.  We're running Advanced Roadmaps, BigPicture, Project Automation, Context Manager, Group Ambassadors, Scriptrunner, Profoma, and a host of other plugins that extend the absolute max customization options to the end user.  The only thing our admin team must do is create the project, which we want to do on behalf of the customer instead of giving them the ability.  

Imagine visiting my Jira site. 

  • You get an account automatically (SAML SSO)
  • Your account gets placed into automated groups based on your work role, organization, employee type, and work location (that automatically updates as you move) (SAML SSO User Sync Magic)
  • You start using one of our standard community projects right away
    • the issues are locked down to you, and people you assign them to
    • the workflow and screens are not editable
  • You need some customization, so you request a project,
    Within a few hours you have a Project, Space, and BigPicture Portfolio.   
    After which, you need almost ZERO support from a Jira Admin.  You have full permissions to:
    • add users or groups to your project roles
      (with a lot of granularity on the exact level of permissions for each of your users due to thoughtful Permission Scheme configs),
    • customize your kanban/scrum boards,
    • create new statuses in your board and edit your workflow from there, if desired
    • customize your workflow in the project settings, if desired
    • edit your screens with on of our 300 generic custom fields,
    • customize the options that are in those fields (Context Manager)
    • need more fields? Create your own project-level fields (Proforma)
    • create automations to simplify your project's functions (Project Automation)
    • self-help learn about Jira & Confluence (Adaptivist Learn)
    • review a rich knowledge space filled with self-help and clever solutions created by the user community specific to our organization
    • connect your data to a Tableau dashboard for rich reporting (Tableau Pro)
    • if you want to use Roadmaps, you can, you just need to configure your project to align with those established rules
    • if you want more control over your program-level planning and reporting, simply create Programs in your BigPicture Portfolio
  • Being self empowered is good, because:
    • there are literally 10000 other users like you wanting their own special little thing,
    • there are only TWO Admins
    • and those two admins do the engineering, architecture, and software updates for 3 independent Jira/Confluence networks all with these same configurations (not including the Dev/Test environments)

Dozens of benefits and force multipliers are realized with this delivery method.  Every user in the organization is empowered to manage any sized project, with no waiting, no asking permission, nothing stopping them.

We have two remaining opportunities to automate further:

  • automate the project lifecycle, so that inactive projects are archived automatically,
    which will allow us to grant end-users permissions to create their own projects
  • set the Resolution globally and automatically - which is why I'm here

If our admin team can automate the setting/clearing of Resolutions, it would solve one of the last manual tasks that we must do. 

These Jira/Confluence environments are engineered to scale.  If we have 50 users, or 50,000, our operation doesn't change (besides the license and server sizes). 


I engineered and built all of this over the past 5 years.  Atlassian asked me to do a presentation at their 2021 Gov Symposium.  So when I say I'm a Jira Expert, please take me at my word.  


Now, back to Resolving issues, which I'm already very close to a solution thanks to @Peter-Dave Sheehan 

Solved: Scriptrunner w/ Automation - Set Resolution (atlassian.com)

import com.atlassian.jira.util.ImportUtils
import com.atlassian.jira.issue.index.IssueIndexingService
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.component.ComponentAccessor

def is = ComponentAccessor.issueService
def iip =is.newIssueInputParameters()
iip.setSkipScreenCheck(true) //only need this if the resolution is not editable
//iip.resolutionId = null
iip.resolutionId = issue.status.statusCategory.primaryAlias == 'Done' ? '10000' : null

def result = is.validateUpdate(currentUser, issue.id, iip)
assert result.valid : result.errorCollection.errors
def updatedIssue = is.update(currentUser, result, EventDispatchOption.DO_NOT_DISPATCH, false).issue

//updatedIssue.resolutionDate = new Date().toTimestamp()
//issue.store()
//update the JIRA index so that jql  for "resolved" work
//boolean wasIndexing = ImportUtils.isIndexIssues()
//ImportUtils.setIndexIssues(true)
//ComponentAccessor.getComponent(IssueIndexingService.class).reIndex(updatedIssue)
//ImportUtils.setIndexIssues(wasIndexing)

 

Suggest an answer

Log in or Sign up to answer
DEPLOYMENT TYPE
SERVER
VERSION
8.22.4
TAGS
AUG Leaders

Atlassian Community Events