Forums

Articles
Create
cancel
Showing results for 
Search instead for 
Did you mean: 

Prevent Linking Unresolved Sub-task Issues to the Resolved Parent Issues

Venugopal Paladi
Contributor
January 18, 2024

Hello All,

I am trying to achieve the following:

If User tries to Link the Unresolved Sub-task Issues to the Resolved Parent issues.

  • It should throw an error i.e (Linking is disallowed as this parent is closed) and it should cancel the link.
  • And,  Add auto comment as same as above error.
  • And, Email the assignee with same error.

Can anyone suggest me how to achieve this?

 

Note: This requirement is for Jira Data Center 8.20 version

 

I have tried with couple of listeners using Scriprunner. There are no errors in the scripts but no exact output as per my requirement.

Here are the 3 to 4 scripts which I tried:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.issue.IssueEvent
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.comments.Comment
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.mail.Email
import com.atlassian.mail.server.MailServerManager
import com.atlassian.mail.server.SMTPMailServer
def issue = event.issue as Issue
def change = event.getChangeLog()?.getRelated("ChildChangeItem")?.find { it.field == "parent" }
// Check if the issue is a sub-task, not resolved, and parent is resolved

def changeItems = event?.getChangeLog()?.getRelated("ChildChangeItem")
def oldParentValue = changeItems?.find { it.field == "parent" }?.oldstring
def newParentValue = changeItems?.find { it.field == "parent" }?.newstring
// Check if the issue is a sub-task, not resolved, and parent is resolved
if (issue.issueType.name == "Sub-task" && !issue.resolution && oldParentValue != newParentValue) {

}
    def currentUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser
    def commentManager = ComponentAccessor.commentManager
    def userManager = ComponentAccessor.userManager
    def mailServerManager = ComponentAccessor.getComponent(MailServerManager)
    def mailServer = mailServerManager.getDefaultSMTPMailServer()
    // Add a comment to the person making the change
    def commentBody = "This change is disallowed as the parent issue is resolved."
    commentManager.create(issue, currentUser, commentBody, false)
    // Email the Assignee (if present)
    def assignee = issue.assignee
    if (assignee) {
        def assigneeEmail = userManager.getUserByKey(assignee.key)?.emailAddress
        if (assigneeEmail) {
            def email = new Email(assigneeEmail)
            email.setSubject("Change Disallowed")
            email.setBody("Dear ${assignee.displayName},\n\nThis change is disallowed as the parent issue is resolved.")
            mailServer?.send(email)
        }
    }


-------------------------------------------------------------------------------------------------------------

import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.link.IssueLinkTypeManager
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.MutableIssue


def issueLinkManager = ComponentAccessor.getIssueLinkManager()
def issueLinkTypeManager = ComponentAccessor.getComponent(IssueLinkTypeManager)
def issue = event.issue as MutableIssue
def subTask = issue
def parentIssue = issue.getParentObject()
def linkTypeName = "blocks"  // Replace with the actual link type name
def linkType = issueLinkTypeManager.getIssueLinkTypes().find { it.name == linkTypeName }
def isSubTaskUnresolved = !subTask.resolution
if (parentIssue && isSubTaskUnresolved && linkType) {
    def existingLinks = issueLinkManager.getIssueLinks(parentIssue.id)
    existingLinks.each { existingLink ->
        if (existingLink.issueLinkType == linkType.name) {
            log.error("Cannot link an Unresolved sub-task to a Resolved parent.")
            
        }
    
    }
}

------------------------------------------------------------------------------------------------------------


import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.status.Status
import com.atlassian.mail.Email
import com.atlassian.mail.server.MailServerManager
import com.atlassian.mail.server.SMTPMailServer

def issue = event.issue as MutableIssue
def user = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def userManager = ComponentAccessor.userManager
def mailServerManager = ComponentAccessor.getComponent(MailServerManager)
def mailServer = mailServerManager.getDefaultSMTPMailServer()
// Check conditions for execution
if (issue.isSubTask() && issue.getStatus() && issue.getParentObject().resolutionDate != null) {
    
    
    
   // Actions:
    // 1. Add comment to user
    issue.addComment("This change is disallowed: Linking unresolved sub-tasks to resolved parent issues is not permitted.")
    // 2. Email assignee (if present)
    def assignee = issue.assignee
    if (assignee) {
        def assigneeEmail = userManager.getUserByKey(assignee.key)?.emailAddress
        if (assigneeEmail) {
            def email = new Email(assigneeEmail)
            email.setSubject("Change Disallowed")
            email.setBody("Dear ${assignee.displayName},\n\nThis change is disallowed as the parent issue is resolved ${issue.key}")
            mailServer?.send(email)
    // Prevent further execution of the event
    throw new RuntimeException("Linking is disallowed as this parent issue is closed")
}}}


-------------------------------------------------------------------------------------------------------------


import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.link.IssueLinkTypeManager
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.event.type.EventDispatchOption



def issueLinkManager = ComponentAccessor.getIssueLinkManager()
def issueLinkTypeManager = ComponentAccessor.getComponent(IssueLinkTypeManager)
def issue = event.issue as MutableIssue
def subTask = issue
def parentIssue = issue.getParentObject()
def linkTypeName = "blocks"  // Replace with the actual link type name
def linkType = issueLinkTypeManager.getIssueLinkTypes().find { it.name == linkTypeName }
def isSubTaskUnresolved = !subTask.resolution
if (parentIssue && isSubTaskUnresolved && linkType) {
    def existingLinks = issueLinkManager.getIssueLinks(parentIssue.id)
    existingLinks.each { existingLink ->
        if (existingLink.issueLinkType == linkType.name)
        if (parentIssue) {
             throw new RuntimeException("Cannot link an Unresolved sub-task to a Resolved parent.")
            
        }
    
    }
}

 

Thanks,

Venu

2 answers

0 votes
Nic Brough -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.
January 18, 2024

Hi Venu,

Most of your code is ok, but it is failing quite early on in the process because you are looking at the wrong thing.

I need to question the part of your question "If User tries to Link the..."

In Jira, we often shorten "issue link" to just "link".  But your code is looking at the parent field as well as issue links, and I do not think I have enough understanding of what you are trying to do here.

There are three things I think you might be trying to do:

  • First, when a sub-task has an issue link added that links it to its parent issue, undo it if the parent is resolved and the sub-task is not. 
    • Or is that for any issue?
    • Why would this matter though?  The sub-task is already inextricably linked to its parent issue, as it is part of it. The issue link being added is totally redundant.
  • Second, you have an issue link type that you are trying to use to make a sub-task look like it has multiple parent issues.
    • This is where the code looks to me to be mixing up the sub-task's actual parent with your issue link that says parent. 
    • You should be looking only at the issue link if it is this case, the parent of the sub-task is irrelevant
    • I would strongly recommend that you do not try to say that a sub-task has many parents as it is confusing for your users.  Tell them something slightly different - that an issue has a dependency on a sub-task, or that the issue needs to be aware of a sub-task which is part of a different issue
  • Third, you are changing the parent of a sub-task. 
    • This means moving the sub-task from one issue to another, which has nothing to do with issue links.

Is it one of those three cases?  Or you are doing something else?

Venugopal Paladi
Contributor
January 19, 2024

Hi @Nic Brough -Adaptavist- 

Yes, First thing I am trying to do. 

(First, when a sub-task has an issue link added that links it to its parent issue, undo it if the parent is resolved and the sub-task is not. )

 

Thanks,

Venu

Nic Brough -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.
January 19, 2024

So, what you are saying is, if someone tries to create a redundant link, remove it?

I mean, say we have

  • ABC-1 Story
    • ABC-4 Subtask of ABC-1
    • ABC-6 Subtask of ABC-1
  • ABC-7 Another story
    • ABC-8 Subtask of ABC-7

Then if Charlie goes into ABC-6 and tries to link it to ABC-1, get rid of the new link?

Also, you only want to do this if the sub-task is unresolved while the parent is not.  The best way to avoid that is actually to use Jira as intended.  Add the (built-in) condition to the Story-level workflow that says "do not allow this issue to close while it still has open sub-tasks".  That way, you'll never need to check the condition!

Venugopal Paladi
Contributor
January 22, 2024

Hi @Nic Brough -Adaptavist- 

I only want to do this if the sub-task is unresolved while the parent is not. Throw an error.

That's all

Thanks!

Nic Brough -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.
January 22, 2024

This is a lot of unneccessary work.  It is far easier (and much easier for your humans) to just add "you can not close this issue when it has open sub-tasks" into your workflow.  No code, no chewing up automations, no emailing people to tell them things have gone wrong.

0 votes
Vishal
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.
January 18, 2024

Hi @Venugopal Paladi 

Could you please elaborate what do you mean by "If User tries to Link the Unresolved Sub-task Issues to the Resolved Parent issues.", please note the subtask cant be created on its own, there should always be a parent ticket to create subtask. Rather the option to create subtask is available in the parent ticket only. Your question is not quite clear.

But if your intention is to just disable subtask creation , if the parent ticket is closed/resolved, then check this answered question. It should help you.

Hope it helps.

Venugopal Paladi
Contributor
January 19, 2024

Hi @Vishal 

I am not looking for creation of sub-tasks.

For Ex:  There is a Task issue and there are Sub-task issues created under Task issue.

And, Imagine there is one more issue type called Change

 

So, There are some users who are linking Sub-task issues which are created under Task to the Change Issue which should not happen. Below is the snip for your reference:

image (14).png

Hope you got it now.

Thanks!

Suggest an answer

Log in or Sign up to answer