How to use ScriptRunner to update Issue Due Date based on fixVersion release Date

Nathan Walker October 25, 2019

Hello,

I have been programming for years but am new to Jira and ScriptRunner.

Sometimes we have to change a versions release date. When I update the fix version release date I want all the issues associated with that version to have updated due dates so that their due date is the new fix version release date.

I found the related article about this topic from 2017 but I don't think it is using script runner and the syntax did not line up with what I am seeing.

Related article: https://community.atlassian.com/t5/Jira-questions/Set-Issue-Due-Date-based-on-fixVersion-release-Date-with-Script/qaq-p/678889

Any help or pointers will be greatly appreciated.

Thanks,

Nathan

 

Here is my  pseudo-code plan.

1. Use Script Listener to trigger when release date is updated.

2. Get version release date.

3. For each issue with a given fix version update issue due date in a similar way to how I did it below.

Is this a good plan?

 

help4.jpg

What I'm trying to do.. 

help3.jpg

 

2 answers

1 accepted

0 votes
Answer accepted
Leo
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
October 25, 2019

Hi @Nathan Walker,

I would use JQLsearch in listener to fetch all issues affected by the event version/release

The listener should be mapped to "VersionUpdatedEvent"

And the below script will update all issues's Due Date with version's Release Date automatically 

import com.atlassian.jira.event.project.VersionUpdatedEvent
import com.atlassian.jira.bc.issue.search.SearchService
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.web.bean.PagerFilter
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.bc.issue.IssueService
import org.apache.log4j.Level
import org.apache.log4j.Logger
import com.atlassian.jira.event.type.EventDispatchOption

def appUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
def searchService = ComponentAccessor.getComponent(SearchService.class)
def issueManager = ComponentAccessor.getIssueManager()
def log = Logger.getLogger("Jira Log")
log.setLevel(Level.DEBUG)

def name = event.getVersion().getName()
def date = event.getVersion().getReleaseDate()
def jqlSearch = "fixVersion = \"${name}\""

SearchService.ParseResult parseResult = searchService.parseQuery(appUser, jqlSearch)
if(parseResult.isValid())
{
def searchResult = searchService.search(appUser, parseResult.getQuery(), PagerFilter.getUnlimitedFilter())
def issues = searchResult.issues.collect {issueManager.getIssueObject(it.id)}

issues.each{ issue ->
issue.setDueDate(new java.sql.Timestamp(date.getTime()))
issueManager.updateIssue(appUser, issue, EventDispatchOption.ISSUE_UPDATED, false)
}
}else {
log.error("Invalid JQL: " + jqlSearch)
}

 

you can remove if there is any unwanted packages imported, I didn't check that

 

BR,

Leo

Nathan Walker October 25, 2019

Thank you @Leo  for the response! 

I'm still learning some basics. I am looking through documentation trying to lean.

Am I  even doing it in the right place? Can I run it in this window like this?

It is not finding the imports. I removed them and I still get a "unable to resolve class SearchService.ParseRusult error. 

Thanks again.

help5.jpghelp6.jpghelp7.jpg

Leo
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
October 25, 2019

Hi @Nathan Walker

It's not accepting/importing "com.atlassian.jira.bc.issue.search.SearchService

And that's the reason you are getting this error. unfortunately I never worked on cloud version. but I don't think the packages are different from server to cloud

Maybe you can refer Adaptavist's cloud documentation

BR,

Leo

Like Nathan Walker likes this
Nathan Walker October 28, 2019

Thank you Leo.

It looks like the cloud version has less available functions at this time.

I'm still looking in to cloud documentation to see how I can update issue due dates when I update there version release date.

Here is another helpful link:  The differences between ScriptRunner for Jira Server and Jira Cloud 

Nathan

gary.lee March 1, 2020

@Nathan Walker Have you solved to do with ScriptRunner Cloud version?

Nathan Walker March 2, 2020
@gary.lee  There is probably a better way to do this but this is what I ended up doing.




// Nathan Walker 11/08/2019

// Update DueDate based on Version Releas Date.

 

// Before running Update the Version Date in Jira to what you want.

// Then replace this ---------v with the version you want to update.

def query = 'fixVersion = "Temp Test Version"'

//-Body----------------------------------------------

 

 

// Search for the issues with the given FixVersion

def searchReq = get("/rest/api/2/search")

.queryString("jql", query)

.queryString("fields", "Flagged")

.asObject(Map)

 

// Verify the search completed successfully

assert searchReq.status == 200

 

//get count of records

def issueCount = (searchReq.body.total).toInteger()

println issueCount

 

//only get the issues from the previous search results

def issues = searchReq.body.issues

 

// Use first issue to find the release versions release date.

def firstIssueKey = issues[0].key

String fixVReleasDate = get('/rest/api/2/issue/' + firstIssueKey).asObject(Map).body['fields']['fixVersions']['releaseDate']

fixVReleasDate = fixVReleasDate.replaceAll("\\[|\\]","")

println "Releas Date: " + fixVReleasDate

 

// for each issue, update the due date

def issueKey

for (i = 0; i < issueCount; i++){

println "in loop: " + i

println "issue Key: " + issues[i].key

issueKey = issues[i].key

    

def result = put("/rest/api/2/issue/${issueKey}")

.header('Content-Type', 'application/json')

.body([

fields: [

                        

duedate: fixVReleasDate

]

])

.asString()

// Validate the issue updated correctly

if (result.status == 204) {

println "Success - The issue with the key of ${issueKey} has been updated to: ${fixVReleasDate}"

} else {

return "${result.status}: ${result.body}"

}

    

}

return "Success! " + issueCount + " issues updated with due date:" + fixVReleasDate
Like Tan Phan likes this
SunilKumar.Shangishetty October 12, 2020

Hi Walker,

I'm new to JIRA scripting. I have a similar requirement too, but instead of declaring fix version static how can we use them dynamically?

0 votes
Suresh Bhandiwad March 28, 2020

@Leo 

Can you please modify above scripts to close issues (transition) when an Version Release Event is triggered using Scriptrunner for Jira custom listener for Jira server?

We are using 8.2.3 method has changed

def issues = searchResult.issues.collect {issueManager.getIssueObject(it.id)}

Thanks!

Leo
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
April 1, 2020

@Suresh Bhandiwad ,

I'm just adding transition script here

def actionId = 41 //41 is my final state transition ID

issues.each { is ->

transitionValidationResult = issueService.validateTransition(currentUser, is.id, actionId,new IssueInputParametersImpl())
if (transitionValidationResult.isValid()) {
transitionResult = issueService.transition(currentUser, transitionValidationResult)
if (transitionResult.isValid())
{ log.warn("Transitioned issue $issue through action $actionId") }
else
{ log.warn("Transition result is not valid") }
}else{
log.warn("The transitionValidation is not valid")
}
}

 

I haven't tested out this script so may require some minor changes

 

BR,

Leo 

Suresh Bhandiwad April 1, 2020

@Leo 

Thank you, it worked!

With Jira 8.2.3, slight modifications:


import com.atlassian.jira.bc.issue.search.SearchService
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.web.bean.PagerFilter
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.bc.issue.IssueService
import org.apache.log4j.Level
import org.apache.log4j.Logger
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.search.SearchResults
import com.atlassian.jira.issue.IssueInputParametersImpl
import com.atlassian.jira.bc.issue.IssueService
import com.atlassian.jira.workflow.JiraWorkflow
import com.atlassian.jira.workflow.WorkflowManager
import com.atlassian.jira.issue.MutableIssue;

def appUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
def searchService = ComponentAccessor.getComponent(SearchService.class)
def issueManager = ComponentAccessor.getIssueManager()

def actionId = 151
IssueService issueService = ComponentAccessor.getIssueService()

def name = event.getVersion().getName()
def date = event.getVersion().getReleaseDate()
def jqlSearch = "fixVersion = \"${name}\""
List<Issue> issues = null

SearchService.ParseResult parseResult = searchService.parseQuery(appUser, jqlSearch)
if(parseResult.isValid())
{
def searchResult = searchService.search(appUser, parseResult.getQuery(), PagerFilter.getUnlimitedFilter())
//issues = searchResult.issues.collect {issueManager.getIssueObject(it.id)}
issues = searchResult.results
issues.each{ issue ->
def transitionValidationResult = issueService.validateTransition(appUser, issue.id, actionId, new IssueInputParametersImpl())
def transitionResult = issueService.transition(appUser, transitionValidationResult)
return transitionResult
}
}else {
log.error("Invalid JQL: " + jqlSearch)
}

Suggest an answer

Log in or Sign up to answer