ScriptRunner "Clones an issue, and links" post-function updating due date of old issue, not clone.

BenK July 27, 2021

Hi there, thanks in advance for any assistance. For reference I'm currently running Jira Server 7.12.1 and ScriptRunner 6.5.0.

I'm currently having a problem with a workflow transition post-function using ScriptRunner's built-in "Clones an issue, and links" function on closure of an issue to do the following:

  • Close the existing issue;
  • Clone a new issue and link it as "Next" from the parent issue;
  • Based on the value of a custom field called "Frequency", increment the due date of the new issue by a number of weeks of months.

I'm trying to achieve the achieve the due-date increment for the new issue using some code in "Additional Issue Actions".  For some very bizarre reason, the due date of the parent/original issue is being updated to the new value, not the due date of the NEW issue.

Please note you can see some "UserMessageUtil.success" calls in a few places of the below code, these are just a temporary diagnostic measure I've added to verify things like the issue key being for the new/current issue, not the old/parent one (it is.)

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.issuetype.IssueType
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.issue.IssueInputParameters
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.bc.issue.*
import static com.atlassian.jira.workflow.TransitionOptions.Builder
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.link.IssueLinkManager
import com.atlassian.jira.issue.link.IssueLink
import org.apache.log4j.Logger
import org.apache.log4j.Level
import java.sql.Date
import java.sql.Timestamp
import com.atlassian.jira.issue.search.SearchProvider
import com.atlassian.jira.jql.parser.JqlQueryParser
import com.atlassian.jira.web.bean.PagerFilter
import com.atlassian.jira.issue.index.IssueIndexingService
import com.atlassian.jira.issue.search.*
import com.atlassian.jira.issue.index.IssueIndexManager
import com.atlassian.jira.issue.index.IssueIndexingService
import com.onresolve.scriptrunner.runner.util.UserMessageUtil
import com.atlassian.jira.event.type.EventDispatchOption


doAfterCreate = {
def issueIndexManager = ComponentAccessor.getComponent(IssueIndexingService)
int dueInMonths = 0
def cfFrequency = customFieldManager.getCustomFieldObjectByName("Frequency")
def cfFrequencyValue = sourceIssue.getCustomFieldValue(cfFrequency).toString()

def oldDueDate = issue.getDueDate()
def updateDate = oldDueDate
def keepDate = updateDate
UserMessageUtil.success('BEFORE the update, Key of the issue that the code thinks is \"issue.\":' + issue.getKey())
UserMessageUtil.success('BEFORE the update, Due date of NEW issue is":' + issue.getDueDate().toString())
UserMessageUtil.success('BEFORE the update, Due date of SOURCE issue is":' + ((MutableIssue) sourceIssue).getDueDate().toString())

switch (cfFrequencyValue) {
case "6 months": updateDate.setMonth(updateDate.getMonth() + 6); issue.setDueDate(updateDate); break;
case "12 months": updateDate.setMonth(updateDate.getMonth() + 12); issue.setDueDate(updateDate); break;
case "18 months": updateDate.setMonth(updateDate.getMonth() + 18); issue.setDueDate(updateDate); break;
case "24 months": updateDate.setMonth(updateDate.getMonth() + 24); issue.setDueDate(updateDate); break;
case "36 months": updateDate.setMonth(updateDate.getMonth() + 36); issue.setDueDate(updateDate); break;
case "3 months": updateDate.setMonth(updateDate.getMonth() + 3); issue.setDueDate(updateDate); break;
case "Biennial": updateDate.setMonth(updateDate.getMonth() + 24); issue.setDueDate(updateDate); break;
case "3months": updateDate.setMonth(updateDate.getMonth() + 3); issue.setDueDate(updateDate); break;
case "Annual": updateDate.setMonth(updateDate.getMonth() + 12); issue.setDueDate(updateDate); break;
case "Fortnightly": updateDate = updateDate.plus(14); issue.setDueDate(updateDate); break; // Fornightly using Timestamp.plus instread of setMonth
case "Quarterly": updateDate.setMonth(updateDate.getMonth() + 3); issue.setDueDate(updateDate); break;
case "Monthly": updateDate.setMonth(updateDate.getMonth() + 1); issue.setDueDate(updateDate); break;
case "3 years": updateDate.setMonth(updateDate.getMonth() + 36); issue.setDueDate(updateDate); break;
case "bi-annually": updateDate.setMonth(updateDate.getMonth() + 6); issue.setDueDate(updateDate); break;
}

UserMessageUtil.success('AFTER the update, Due date of NEW issue is":' + issue.getDueDate().toString())
UserMessageUtil.success('AFTER the update, Due date of SOURCE issue is":' + ((MutableIssue) sourceIssue).getDueDate().toString())
UserMessageUtil.success('AFTER the update, Key of the issue that the code thinks is \"issue.\":' + issue.getKey())
((MutableIssue) sourceIssue).setDueDate(keepDate) // For some reason (this is not supposed to be how it works with ScriptRunner) this code is also updating the PARENT issue's original date. This sets it back.

The kind of message box results I'll get back are as follows: 

yep, this is stupid.png

What's even more bizarre, is when checking issue "OSCISSUE-2440" (the one that's just been created) after this process, its due date value is actually 2057. The one that gets updated to 2060 will be the original issue.

I'm kind of at my wits-end with this. I've tried all sorts of things like taking "issue.setDueDate(updateDate)" out of the switch statement (only using update.setMonth()) and doing something wholely overcomplicated and unnecessary like building up a JQL query string, plugging it into a searchProvider, cycling through the results (of which there would only be one) and manually trying to set the due date like shown below:

def jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser.class)
def searchProvider = ComponentAccessor.getComponent(SearchProvider.class)
def issueManager = ComponentAccessor.getIssueManager()
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def query = jqlQueryParser.parseQuery("project = OSCISSUE and key = \"" + issue.getKey() + "\"")
UserMessageUtil.success('Query for update is::' + query)
def results = searchProvider.search(query, user, PagerFilter.getUnlimitedFilter())
//"Cycle through" the results (which should be only one, i.e. the new cloned issue with the matching key)
results.each {documentIssue ->;

((MutableIssue) documentIssue).setDueDate(updateDate)
ComponentAccessor.getIssueManager().updateIssue(user, (MutableIssue) documentIssue, EventDispatchOption.ISSUE_UPDATED, false)
issueIndexManager.reIndex((MutableIssue) documentIssue)
}

 Obviously this last chunk of code is janky as hell and not part of what I want to end up with, but just an example to show how desperate I'm getting.

Does anyone have any ideas why ScriptRunner would be updating the date of the old issue instead of the new one? Thanks.

0 answers

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events