Scriptrunner listener to update custom date/time field For Cloud JIRA

Darren Xie November 1, 2017

Hi All,

I need a listener that will add current timestamp (date or datetime) to a custom date/time fields when another field (Story Points) is updated, for JIRA Cloud.

For example, if custom checkbox "Story Points" is edited, the listener detects this change and will timestamp the custom date/time field "StoryPointsLastChangeDate".

And, should the StoryPointsLastChangeDate a 'date' field or a 'datetime' custom field?

Thanks to @Conor McGmail @Thanos Batagiannis _Adaptavist_ .

I fond your post at : https://community.atlassian.com/t5/Jira-questions/Scriptrunner-listener-to-update-custom-date-time-field/qaq-p/387444

 

But for JIRA Cloud, it does not work.

my script listner:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder

import java.sql.Timestamp

Issue issue = issue
def change = event?.getChangeLog()?.getRelated("ChildChangeItem").find {it.field == "Story Points"}
if (change) {
def cf = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName("StoryPointsLastChangeDate")
def changeHolder = new DefaultIssueChangeHolder()
def now = new Timestamp(new Date().getTime())
cf.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(cf), now),changeHolder)
}

 

The errors:

2017-11-02 03:20:45.232 ERROR - startup failed:
Script1.groovy: 3: unable to resolve class com.atlassian.jira.issue.ModifiedValue
@ line 3, column 1.
import com.atlassian.jira.issue.ModifiedValue
^

Script1.groovy: 2: unable to resolve class com.atlassian.jira.issue.Issue
@ line 2, column 1.
import com.atlassian.jira.issue.Issue
^

Script1.groovy: 1: unable to resolve class com.atlassian.jira.component.ComponentAccessor
@ line 1, column 1.
import com.atlassian.jira.component.ComponentAccessor
^

Script1.groovy: 4: unable to resolve class com.atlassian.jira.issue.util.DefaultIssueChangeHolder
@ line 4, column 1.
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
^

4 errors

2017-11-02 03:20:45.653 ERROR - Class: com.adaptavist.sr.cloud.events.ScriptExecution, Config: null

 

Any help is much appreciated.

 

Regards,

Darren

3 answers

1 accepted

0 votes
Answer accepted
Andrzej Wieczorek November 2, 2017

I have created an example code for you. Please have a look at the below code.

import java.time.ZonedDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter

def storyPointsCheckboxFieldId = "customfield_10718"
def storyPointsLastChangeDateFieldId = "customfield_10719"

def customFieldChange = changelog.items.find { item -> item.fieldId == storyPointsCheckboxFieldId }
if (customFieldChange) {
logger.info("Custom field has been updated from value: {} to value: {}", customFieldChange.fromString, customFieldChange.toString)
def currentDateTime = ZonedDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
logger.info("Making a request to update custom field id: {} with value: {}", storyPointsLastChangeDateFieldId, currentDateTime)

def result = put('/rest/api/2/issue/ADSD-2')
.header('Content-Type', 'application/json')
.body([
fields:[
(storyPointsLastChangeDateFieldId): currentDateTime
]
])
.asString()
if (result.status == 204) {
logger.info("Successfully updated field {} with value {}", storyPointsLastChangeDateFieldId, currentDateTime)
} else {
logger.error("Failed update field: {}. Jira responded {}: {}", storyPointsLastChangeDateFieldId, result.status, result.body)
}

}

You only need to replace ids of custom fields, i.e. storyPointsCheckBoxFieldId and storyPointsLastChangeDateFieldId.

In my example field storyPointsLastChangeDateFieldId is a 'Date Time Picker' custom field, but storyPointsCheckboxFieldId has a type 'Checkboxes'.

Darren Xie November 3, 2017

Thank you @Andrzej for you quick help. This example is really great help.

 

I have several questions:

1. Seems the currentDateTime could be sent to both the date and date time custom fields. No need to get a currentDate, right?

2. how to update both the date custom field and date time custom field? Is it possible to put in one put REST call?

now I could do it via two put REST call.....

// def resultDate = put('/rest/api/2/issue/${issue.key}')
def resultDate = put('/rest/api/2/issue/ACM-713')
.header('Content-Type', 'application/json')
.body([
fields:[
(StoryPointsLastChangeDateID): currentDateTime
]
])
.asString()
if (resultDate.status == 204) {
logger.info("Successfully updated field Story Points Last Change Date with value {} for issue {}", currentDateTime, issue.id)
logger.info(" ")
} else {
logger.error("Failed update field Story Points Last Change Date. Jira responded {}: {}", resultDate.status, resultDate.body)
logger.info(" ")
}

logger.info("Making a request to update custom field Story Points Last Change Date Time with value: {}", currentDateTime)
logger.info(" ")
// def resultDateTime = put('/rest/api/2/issue/${issue.key}')
def resultDateTime = put('/rest/api/2/issue/ACM-713')
.header('Content-Type', 'application/json')
.body([
fields:[
(StoryPointsLastChangeDateTimeID): currentDateTime
]
])
.asString()
if (resultDateTime.status == 204) {
logger.info("Successfully updated field Story Points Last Change Date Time with value {} for issue {}", currentDateTime, issue.id)
logger.info(" ")

it throw errors if I put two fields in one put call like:

 def resultDate = put('/rest/api/2/issue/ACM-713')
.header('Content-Type', 'application/json')
.body([
fields:[
(StoryPointsLastChangeDateID): currentDateTime
(StoryPointsLastChangeDateTimeID): currentDateTime
]
])
.asString()

 

3.

def result2 = put('/rest/api/2/issue/${issue.id}')
put('/rest/api/2/issue/${issue.id}')
and 
put('/rest/api/2/issue/${issue.key}')

return error:

2017-11-03 06:25:49.291 WARN - PUT request to /rest/api/2/issue/${issue.id} returned an error code: status: 404 - Not Found
body: {"errorMessages":["Issue does not exist or you do not have permission to see it."],"errors":{}}

 

but hard code works:

def result2 = put('/rest/api/2/issue/ACM-713')

returns:

2017-11-03 06:28:42.134 INFO - PUT /rest/api/2/issue/ACM-713 asString Request Duration: 1443ms

 

 

So how to make it work while not hard code?

 

4. Is it possible that, how to make the related date and date time custom field only editable by the Script Runner or maybe as well as some admin users/groups?

1 vote
Andrzej Wieczorek November 6, 2017

1) I'm not sure, you need to test it whether date time fits in date field or not.

2) What type of error did you get when you put two fields in one call?

3) There is a bug in the code. 

Please replace:

 put('/rest/api/2/issue/${issue.id}')

with: 

 put("/rest/api/2/issue/${issue.id}")

Otherwise code ${issue.id} won't be evaluated.

Darren Xie November 6, 2017

Awesome! it works now! Really appreciate your help on this!

 

BTW, any idea about this?

4. Is it possible that, make the related date and date time custom field only editable by the Script Runner or maybe as well as some admin users/groups?

0 votes
ragnar April 25, 2018

@Andrzej Wieczorek

Hi

I tried the 

import java.time.ZonedDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter

def storyPointsCheckboxFieldId = "customfield_10718"
def storyPointsLastChangeDateFieldId = "customfield_10719"

def customFieldChange = changelog.items.find { item -> item.fieldId == storyPointsCheckboxFieldId }
if (customFieldChange) {
logger.info("Custom field has been updated from value: {} to value: {}", customFieldChange.fromString, customFieldChange.toString)
def currentDateTime = ZonedDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
logger.info("Making a request to update custom field id: {} with value: {}", storyPointsLastChangeDateFieldId, currentDateTime)

def result = put('/rest/api/2/issue/ADSD-2')
.header('Content-Type', 'application/json')
.body([
fields:[
(storyPointsLastChangeDateFieldId): currentDateTime
]
])
.asString()
if (result.status == 204) {
logger.info("Successfully updated field {} with value {}", storyPointsLastChangeDateFieldId, currentDateTime)
} else {
logger.error("Failed update field: {}. Jira responded {}: {}", storyPointsLastChangeDateFieldId, result.status, result.body)
}

}

Got a few error right from the start

result:

groovy.lang.MissingPropertyException: No such property: changelog for class: Script1
at Script1.run(Script1.groovy:8)
at Script1$run.call(Unknown Source)
at Script1$run.call(Unknown Source)
at com.adaptavist.sr.cloud.workflow.AbstractScript.evaluate(AbstractScript.groovy:30)
at com.adaptavist.sr.cloud.workflow.AbstractScript$evaluate$0.callCurrent(Unknown Source)
at com.adaptavist.sr.cloud.events.ScriptExecution.run(ScriptExecution.groovy:27)
at ConsoleScriptExecution2_groovyProxy.run(Unknown Source)

Logs:

No such property: changelog for class: Script1 on line 8
Class: com.adaptavist.sr.cloud.events.ConsoleScriptExecution, Config: [:]

 

Could you help me with this? 

Andrzej Wieczorek April 25, 2018

Hi,

'changelog' binding is only available for Issue Updated event. Could you please tell me for which event type the script was executed?

ragnar April 25, 2018

Right so I found out that this error is only in the Script Console and in the script listener everything is fine.

Now it just wont update the right fields:

2018-04-25 13:55:52.335 INFO - Custom field has been updated from value: null to value: fyjdgtjrt
2018-04-25 13:55:52.336 INFO - Making a request to update custom field id: customfield_10210 with value: 2018-04-25T13:55:52.335
2018-04-25 13:55:52.603 WARN - PUT request to /rest/api/2/issue/ADSD-2 returned an error code: status: 404 - Not Found
body: {"errorMessages":["Issue does not exist or you do not have permission to see it."],"errors":{}}
2018-04-25 13:55:52.604 INFO - PUT /rest/api/2/issue/ADSD-2 asString Request Duration: 266ms
2018-04-25 13:55:52.605 ERROR - Failed update field: customfield_10210. Jira responded 404: {"errorMessages":["Issue does not exist or you do not have permission to see it."],"errors":{}}

 Manual editing works fine

ragnar April 26, 2018

@Andrzej Wieczorek

Could you direct me to some direction why this sort of error message is appearing? As I mentioned manually every user can edit issues, but for some reason scriptrunner has problems with it.

Andrzej Wieczorek April 26, 2018

Could you please try to use 'Permission helper' in order to check if 'ScriptRunner for Cloud' user can edit the issue?

Screen Shot 2018-04-26 at 10.57.48.png

Andrzej Wieczorek April 26, 2018

Make sure that you are using ScriptRunner user for that operation, if you are using Current User, please make sure that given user has a permission to edit the issue.

ragnar April 26, 2018

I tried running it as both current user and scriptrunner user. Same issues for both. Permission helper also confirmed that both of them have the right amount of access.

Suggest an answer

Log in or Sign up to answer