/
Post function script to update issue fields from ScriptRunner does not generate revisions in easeRequirements

DATA CENTER AND SERVER | CLOUD

Post function script to update issue fields from ScriptRunner does not generate revisions in easeRequirements

Problem

When updating an issue via post function script from ScriptRunner, the changes do not generate revisions in easeRequirements, even though the changes appear in the history of Jira issue view.

Cause

Scripts from ScriptRunner do not always fire an IssueChangedEvent. This event notifies easeRequirements that a change has occurred in an issue. The listeners in easeRequirements cannot catch such changes from the scripts, hence revisions for the changes cannot be generated.

Solution

The script can be updated to fire an event that can be caught by the listeners in easeRequirements. There are 2 options to achieve this.

1. EventDispatchOption

When updating an issue using updateIssue from IssueManager, you have the option to specify EventDispatchOption. You can use this to fire an event when updating an issue. However, EventDispatchOption.ISSUE_UPDATED does not work for easeRequirements. The way the listeners in easeRequirements are programmed excludes this type of event in revision generation, but the event is caught in our listeners.

Refer to the sample script below on how to fire an event using this option.

import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.issue.MutableIssue //"YOUR_ISSUE_KEY_HERE" def issueKey = "PROJECTKEY-10" def customFieldManager = ComponentAccessor.getCustomFieldManager() def issueManager = ComponentAccessor.getIssueManager() def issueService = ComponentAccessor.getIssueService() def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser() def issue = issueManager.getIssueObject(issueKey) as MutableIssue if (!issue) { log.warn("Issue with key ${issueKey} not found") return } def customField = customFieldManager.getCustomFieldObjectsByName("SSL").first() if (!customField) { log.warn("Custom field 'SSL' not found") return } def currentValue = issue.getCustomFieldValue(customField) if (currentValue != "updated thru script") { issue.setCustomFieldValue(customField, "updated thru script") issueManager.updateIssue(user, issue, com.atlassian.jira.event.type.EventDispatchOption.DO_NOT_DISPATCH, false) log.info("Updated SSL field for issue ${issue.key}") } else { log.info("SSL field is already set to 'updated thru script' for issue ${issue.key}") }

Firing events with EventDispatchOption via updateIssue without any changes made to the issue will not fire an event.

 

2. publish(Object event)

This function from Jira allows you to fire an event manually. This is the recommended way to fire an event because you can choose an EventType in contrast to the limited options of EventDispatchOption. This option requires more changes as it needs to get the ChangeGroup first that easeRequirements can reference to in order to make a revision.

Certain types of EventType are excluded from revision generation. Refer to Limitations.

Refer to the sample script below on how to fire an event using this option.

import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.issue.Issue import com.atlassian.jira.issue.MutableIssue import com.atlassian.jira.issue.changehistory.ChangeHistoryManager import com.atlassian.jira.issue.changehistory.ChangeHistory import com.atlassian.jira.user.ApplicationUser import com.atlassian.jira.event.type.EventType import com.atlassian.jira.event.issue.IssueEvent import com.atlassian.event.api.EventPublisher import org.ofbiz.core.entity.GenericValue // Get required services def issueManager = ComponentAccessor.getIssueManager() def customFieldManager = ComponentAccessor.getCustomFieldManager() def changeHistoryManager = ComponentAccessor.getChangeHistoryManager() def ofBizDelegator = ComponentAccessor.getOfBizDelegator() def eventPublisher = ComponentAccessor.getComponent(EventPublisher) def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser() // Define the issue and new values def issue = issueManager.getIssueObject("ISSUE-123") // Replace with your issue key def customField = customFieldManager.getCustomFieldObjectByName("Custom Field Name") // Replace with your custom field name def newValue = "New Value" // Replace with your new value // Update the issue issue.setCustomFieldValue(customField, newValue) issue.setDescription(newValue) issueManager.updateIssue(user, issue, com.atlassian.jira.event.type.EventDispatchOption.DO_NOT_DISPATCH, false) // Retrieve the change history for the issue def changeHistories = changeHistoryManager.getChangeHistoriesForUser(issue, user) // Get the latest change history def latestChangeHistory = changeHistories.last() // Retrieve the ChangeGroup as a GenericValue def changeGroupId = latestChangeHistory.getId() def changeGroup = ofBizDelegator.findById("ChangeGroup", changeGroupId) // Create the IssueEvent def event = new IssueEvent( issue, // Issue user, // ApplicationUser null, // Comment (null if not applicable) null, // Worklog (null if not applicable) changeGroup, // GenericValue changeGroup [:], // Params (empty map if not applicable) EventType.ISSUE_UPDATED_ID // Event type ID ) // Fire the event eventPublisher.publish(event)

Limitations

  1. EventDispatchOption

    1. Exclusions

      1. ISSUE_UPDATED

    2. Caution

      1. ISSUE_DELETED – The issue will be removed from the tree view. However, it can be added via "Add existing issues".

  2. publish(Object event)

    1. Exclusions

      1. ISSUE_CREATED_ID

      2. ISSUE_COMMENT_DELETED_ID

      3. ISSUE_UPDATED_ID

Other Findings

  1. Multiple scripts are supported as long as they fire an event.

  2. Multiple events are supported.

    1. Caution

      1. Multiple events fired from eventPublisher.publish(event) may cause multiple generated revisions.

      2. Combining options 1 and 2 from Solution may cause multiple generated revisions.

  3. Blacklisted fields are handled.