Warn that prior subtask not complete

LaurieC
Contributor
June 7, 2021

We have a set of subtasks that need to be completed in a certain order. The subtasks are often assigned to different people. I would like to show a warning if someone starts subtask 3 before subtask 2 is completed.

We do have Scriptrunner. Is there a way to accomplish this?

1 answer

1 accepted

1 vote
Answer accepted
Hyrum Steffensen _Appfire_
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.
June 7, 2021

Hello Laurie,

I have an idea you may like, but I have only tested it out on Power Scripts. First I will post the equivalent script in Groovy based on this Adaptavist documentation on validators and this one on subtasks.

The idea here is to loop through all the subtasks and break the loop once the current subtask is found. If the loop completes, throw an validator error. 

def parent = issue.getParentObject().getIssueTypeObject().getName()

def subTasks = parent.getSubTaskObjects()
subTasks.each {

    if (it.getKey() == issue.getKey()) {

        break;

    }

    if (it.getStatusObject().getName() != "Done") {

        throw new InvalidInputException("subtasks","Not all previous subtasks completed")

    }

}

I did try this out on Power Scripts. Here is the script I used. Please see this documentation on subtasks routine and this one on validators.

string [] subtasks = subtasks(parent);

for (string subtask in subtasks) {

    if (subtask == key) {

        break;

    }

    if (subtask.status != "Done") {

        return false, "status", "Previous subtasks have not been completed";

    }

}

Full disclosure, I am a Product Engineer for Power Scripts and work for Anova Apps, an Appfire company.

LaurieC
Contributor
June 8, 2021

Wow! Thanks so much for jumping in on this @Hyrum Steffensen _Appfire_ ! Let me try it out.

Hyrum Steffensen _Appfire_
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.
June 8, 2021

Sure thing, Laurie! Please let me know how it goes!

Hyrum

LaurieC
Contributor
June 8, 2021

Well, I'm not a developer, so I got a little stuck. I'll still digging, but would love some help if anyone can offer it.

Here's the code I'm using.

import com.opensymphony.workflow.InvalidInputException


def parent = issue.parentObject 

def subTasks = parent.getSubTaskObjects()
subTasks.each {

if (it.getKey() == issue.getKey()) {
break;
}

if (it.getStatusObject().getName() != "Testing") {
throw new InvalidInputException("subtasks","Not all previous subtasks completed")
}
}

I'm getting the following error:

The script could not be compiled:

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed: Script32.groovy: 14: the break statement is only allowed inside loops or switches @ line 14, column 9. break; ^ 1 error

.

It seems that it isn't seeing the loop. Suggestions?

LaurieC
Contributor
July 15, 2021

@Hyrum Steffensen _Appfire_ any thoughts here? I realize you don't do Scriptrunner.

 

Has anyone with Scriptrunner done something similar to this? I'd love some input here. :)  

Hyrum Steffensen _Appfire_
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.
July 15, 2021

Hello Laurie!

Thanks for reaching out! How about something like the following. In the code below, I have two subtasks, "EX-2" and "EX-3". Here are the steps the code takes:

  • First the "issue" variable is set to "EX-3". You probably do not need to do this as "issue" should be provided by the validator context.
  • Set the parent key to "parent"
  • Set all the subtasks of the parent to "subTasks"
  • Loop through the subtasks
  • Use regex to extract the numbers of the issue key
  • The if statement checks:
    • if the subtask is less than the issue AND
    • if the subtask is done
    • If both conditions are met, throw an error
import com.opensymphony.workflow.InvalidInputException
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue

def issueManager = ComponentAccessor.getIssueManager()
def issue = issueManager.getIssueObject("EX-3")

def parent = issue.getParentObject()
def subTasks = parent.getSubTaskObjects()

for (int i = 0; i < subTasks.size(); i++) {
def subtaskNumber = subTasks[i].getKey().findAll( /\d+/ )*.toInteger()[0]
def originalIssueNumber = issue.getKey().findAll( /\d+/ )*.toInteger()[0]

if (subtaskNumber < originalIssueNumber && subTasks[i].getStatus().getName() != "Done") {
return subTasks[i];
// throw new InvalidInputException("subtasks","Not all previous subtasks have been completed")
}
}

As previously stated, the "issue" variable should be provided by the validator context. As such, your code would look like this:

import com.opensymphony.workflow.InvalidInputException

def parent = issue.getParentObject()
def subTasks = parent.getSubTaskObjects()

for (int i = 0; i < subTasks.size(); i++) {
def subtaskNumber = subTasks[i].getKey().findAll( /\d+/ )*.toInteger()[0]
def originalIssueNumber = issue.getKey().findAll( /\d+/ )*.toInteger()[0]

if (subtaskNumber < originalIssueNumber && subTasks[i].getStatus().getName() != "Done") {
throw new InvalidInputException("subtasks","Not all previous subtasks have been completed")
}
}

I hope that helps!

Regards,

Hyrum

LaurieC
Contributor
July 16, 2021

Thanks so much @Hyrum Steffensen _Appfire_ for taking the time! Let me try this out and let you know how it goes.

Hyrum Steffensen _Appfire_
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.
July 16, 2021

Indeed! I would love to hear how it turns out! 

Hyrum

LaurieC
Contributor
July 21, 2021

@Hyrum Steffensen _Appfire_ HUGE thanks again! I just realized I didn't respond to you to let you know this worked! Here's what I used:

 

import com.opensymphony.workflow.InvalidInputException

log.setLevel(org.apache.log4j.Level.DEBUG)

def parent = issue.getParentObject()
log.debug "parent issue is $parent"
def subTasks = parent.getSubTaskObjects()

for (int i = 0; i < subTasks.size(); i++) {
def subtaskNumber = subTasks[i].getKey().findAll( /\d+/ )*.toInteger()[0]
log.debug "subtaskNumber is $subtaskNumber"
def startedIssueNumber = issue.getKey().findAll( /\d+/ )*.toInteger()[0]
log.debug "started Issue number is $startedIssueNumber"
def evaluation = subtaskNumber < startedIssueNumber
log.debug "subtaskNumber is less than started issue number $evaluation"
def subtaskStatus = subTasks[i].getStatus().getName()
log.debug "status of subtaskNumber is $subtaskStatus"

if (subtaskNumber < startedIssueNumber && subTasks[i].getStatus().getName() != "Pass") {
log.debug "should throw error"
throw new InvalidInputException("Not all previous subtasks have been completed")
}
}

Worked like a charm!

Thanks again!
Laurie

Hyrum Steffensen _Appfire_
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.
July 21, 2021

Fantastic! Glad it worked, Laurie! 

Please remember to mark this as the answer so that other Community users can find it.

Regards,

Hyrum

Like LaurieC likes this

Suggest an answer

Log in or Sign up to answer