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

Clearing the resolution when moving from a "Done" status category to any other

Fredrik August 31, 2020

Hey there!

I just wanted to share my solution for clearing the Resolution on a status transition (if moved from Done to To-Do or In-Progress) and wanted to ask for some feedback - perhaps I've missed something, or I'm doing something very silly. 

The reason I haven't used Post Functions to clear the resolution is to have 1 script that covers all cases and avoid having to setup and maintain multiple post-functions (e.g. if a new status is added, it's covered automatically).

Using ScriptRunner I've created a Listener that listens to All Issue Events for my particular project (there didn't seem to be one for just listening to status transitions). 

Here's the script:

 

import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.status.category.StatusCategory
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.type.EventDispatchOption

/*
A status Transition listener that clears the Resolution status if an issue is
moved from a "Complete" status category any of the to the other categories ("To-Do" / "In Progress").
*/

// The issue provided to us in the binding
MutableIssue issue = event.issue as MutableIssue

// Not an epic? We only care about those. Early exit.
if (issue.getIssueType().getName() != "Epic") {
return
}

// No changelog (e.g. an edit with only a comment)? Early exit.
if (event.getChangeLog() == null) {
return
}

def statusChangeItems = ComponentAccessor.getChangeHistoryManager().getChangeItemsForField(issue, 'status')

// No status changes? It's a new issue. Early exit.
if (statusChangeItems.isEmpty()) {
return
}

def lastTransitionChangeItem = statusChangeItems?.last()
def fromStatus = lastTransitionChangeItem.fromString
def toStatus = lastTransitionChangeItem.toString

// No status change? Early exit.
if (fromStatus == toStatus) {
return
}

def eventFiredTimestamp = event.getChangeLog().created
def changeItemTimestamp = lastTransitionChangeItem.created

// If the last status change was at the exact same time as the event we can (somewhat?)
// safely deduce that this event was fired because of a status transition
if(changeItemTimestamp != eventFiredTimestamp) {
return
}

StatusCategory fromStatusCategory = null
StatusCategory toStatusCategory = null
def workflow = ComponentAccessor.getWorkflowManager().getWorkflow(issue)

// Find category of status by name
workflow.getLinkedStatusObjects().each {
if ("${it.name}" == fromStatus) {
fromStatusCategory = it.statusCategory
}

if ("${it.name}" == toStatus) {
toStatusCategory = it.statusCategory
}
}

// Couldn't find status categories from status name? (Shouldn't happen..)
if (fromStatusCategory == null || toStatusCategory == null) {
log.warn ("Could not find category for from- (${fromStatus}), or to-, status (${toStatus}).")
return
}

// Not a transition from a "Complete" (green) status? Not interested. Early exit.
if (fromStatusCategory.getKey() != StatusCategory.COMPLETE) {
return
}

// Transition to "Complete" status? Don't want to clear resolution. Early exit.
if (toStatusCategory.getKey() == StatusCategory.COMPLETE) {
return
}

// Let's clear that resolution!
def issueManager = ComponentAccessor.getIssueManager()
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
issue.setResolution(null)
issueManager.updateIssue(user, issue, EventDispatchOption.DO_NOT_DISPATCH, false)

 

1 comment

Comment

Log in or Sign up to comment
Daniel Ebers
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.
October 4, 2020

Hi Fredrik,

welcome to the Atlassian Community!

I like your approach to have a resolution set for Epics and I believe your users will have a great benefit from this solution.
Setting a resolution in all of the existing workflows can be a tedious task and is easy to be forgotten. With a Script Listener you, as well all people maintaining workflows, can neglect this in the future (at least for Epics), perfect!

Regarding the technical details there are not many things that came to my mind. In case you are going to extend the solution to more Issue Types later on, it could make sense to check if the solution overall puts reasonable load to the instance. This probably depends if there are many users on your instance and more specifically how many issues are transitioned troughout one day.

Apart from that I am not familiar with every function you used but I believe the Listener will work as it looks well prepared - it even makes use of comments which is pretty awesome!

There might be one pitfall left on organizational basis but this heavily depends on the expectations of your userbase. I came across several scenarios where we added custom scripts to Jira to optimize user experience. Basically one like in your case but for other scenarios like

  • unassign an issue if the Assignee is due to leave the company within the next month
  • remind users when an issue is due within the next days
  • update several fields when a specific condition is met
    (to only name a few)

Users expect these automations to work flawlessly all the time - which means you have to maintain the Listener (or whatever is used to meet the requirement) all the time. Before a Jira upgrade you must always make sure the script is still compatible with a new Jira version and/or ScriptRunner release.
Also, it turned out, solutions like this attract the attention of users/managers/stakeholders in general. Then it won't stay with one automation that makes life easier but you see requests for more and more automation which asks the question for scale

  • who else will maintain the Groovy script (in case of vacation or illness)?
  • is the sum of them putting too much load on the instance
  • where is the point where we must say: "here begins the plain usage of your project - we cannot automate everything for you as it is part of your daily job").

These days there are additional solutions for automation jobs out (in Jira cloud meanwhile there is even built in functionality) which lower the burden on the admin team a bit but the details of implementation might differ a lot from company to company.

As a summary I believe the approach brings much value and is worth to be implemented. Maybe some other users from Atlassian Community have some feedback (probably even a bit more technical?) to come up with.

I wish you a great day!

Cheers,
Daniel

Like Fredrik likes this
TAGS
AUG Leaders

Atlassian Community Events