Custom Groovy Post Functions in Jira Workflows

25 Sep, 2018 | 4 minutes read

What is a Jira workflow?

A Jira workflow is a basic part of Jira since it describes a process.  All the statuses and transitions in a workflow in fact describe the path that an issue goes through from its creation to its closing. Except for its basic meaning, the workflow is where we can set some limitations, include phases of approvals, create automatic links, or even be in synchronization with development tools.

Jira workflow
(Picture 1 – Jira Workflow)

There is a lot to be said if we want to explain one workflow in all its aspects. In this blog we are going to describe one part of the workflow, in face we are going to talk about adding a post function to a workflow’s transition.

In an extremely basic workflow that means:

  1. Creating an Issue, to reflect a new task. This will have a “To Do” status.
  2. Marking it as “In progress” once the work is begun.
  3. Then, when the task is finished, you can mark it as being “Done”. And you’ve already gone from one end of the workflow to the other.
Simple workflow
(Picture 2 – Simple Workflow)

Workflow Statuses and Transitions

A status represents the state of an issue at a specific point in your workflow. A transition is a link between two statuses that enables an issue to move from one status to another. In order for an issue to move between two statuses, a transition must exist. A transition is a one-way link, so if an issue needs to move back and forth between two statuses, two transitions should be created.

Jira workflow statuses and transitions
(Picture 3 – Jira Workflow Statuses and Transitions)

Workflow post functions

Every Jira transition has the following essential post functions performed in this order:

  1. Set an issue status to the linked status of the destination workflow step
  2. Add a comment to an issue if one is entered during a transition
  3. Update change history for an issue and store the issue in the database
  4. Re-index an issue to keep indexes in sync with the database
  5. Fire a Generic Event that can be processed by the listeners

These essential post functions cannot be deleted from a transition or reordered.

Default Jira workflow post functions
(Picture 4 – Default Jira workflow post functions)

Adding a post function on transition

Jira includes several optional post functions that can be added to transitions.

  1. Assign to Current User
  2. Assign to Lead Developer
  3. Assign to Reporter
  4. Create a Perforce Job Function
  5. Notify Hipchat
  6. Trigger a Webhook
  7. Update Issue Field

To add a post function to a transition, edit the workflow that contains the transition, select the transition, then click Post functions in the properties panel for the transition.

Add a post function to a transition:

  1. Click Workflows and then Edit for the relevant workflow.
  2. In diagram mode, select the transition arrow. In text mode, select the transition’s name from the Transitions (id) column.
  3. In diagram mode, click Post functions in the properties panel to show the triggers configured for the transition. In text mode, select the Post functions tab.
Adding post function on transition
(Picture 5 – Adding post function on transition)
Post functions on transition
(Picture 6 – Post functions on transition)

When you click Add post function you can choose from the available post functions, and set any necessary parameters.

Adding pre-defined post function on transition
(Picture 7 – Adding pre-defined post function on transition)

Using a custom Groovy post functions

The list of additional post functions can be enriched by installing different plugins. It is possible to develop and implement Jira plugin that will support definition of Workflow Post Functions based on Dynamic Groovy Script specified in the Jira user interface (something we have done in our company). In the following text we will explain how to add post function of type Groovy Script Function to a transition (the presumption is that the plugin is already developed and installed on the JIRA instance).

When the workflow we want to make changes in is in Edit mode, first we select the transition (for example transition Create tasks) and then we click Post functions in the properties panel for the transition.

This takes us to a window that represents all the Triggers, Conditions, Validators and Post Functions (if any) defined for the transition. In the Post Functions part besides the essential five post functions mentioned previously, the Add post function button is in the right upper corner enabling us to add an additional post function to the transition.

Adding post functions on transition
(Picture 8 – Adding post functions on transition)

By clicking this button, we go to the Add Post Function To Transition window, where one of the options to choose is Groovy Script Function (The Groovy Script Function Plugin).

Adding Groovy post functions on transition
(Picture 9 – Adding Groovy post functions on transition)

When selected by clicking Add button we get this window:

Add parameters to function
(Picture 10 – Add parameters to function)

Here is where we specify the Groovy code that will make the needed changes. The code below will show the adding or removing watchers from a ticket.

Adding watchers using custom Groovy post function

//Add WATCHERS to the ticket - all members from the group "Arhiva"

import com.atlassian.jira.component.ComponentAccessor 
import com.atlassian.jira.issue.Issue
def userManager = ComponentAccessor.getUserManager()
def groupManager = ComponentAccessor.getGroupManager()
def issueManager = ComponentAccessor.getIssueManager()
def watcherManager = ComponentAccessor.getWatcherManager()
groupManager.getUsersInGroup("Arhiva").each {
	def issue = issueManager.getIssueObject(issue.id)
	watcherManager.startWatching(it, issue)

Removing watchers using custom Groovy post function

//Remove watchers from ticket

import com.atlassian.jira.component.ComponentAccessor
def watcherManager = ComponentAccessor.getWatcherManager()
def userUtil = ComponentAccessor.getUserUtil()
watcherManager.getCurrentWatcherUsernames(issue).each {
    watcherManager.stopWatching(userUtil.getUser(it), issue)
}

Assign issue to the user selected form the custom list

//Assign issue to a user (by FullName) selected in a List

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.bc.user.search.UserSearchService;
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def direktor = issue.getCustomFieldValue(customFieldManager.getCustomFieldObject(10300)).getValue()
UserSearchService userSearchService = ComponentAccessor.getComponent(UserSearchService.class);
def users = userSearchService.findUsersByFullName(direktor)
if (users) {
    issue.setAssignee(users.first())         // an ApplicationUser 
}

Conclusion

Jira provides a wide range of functionalities to realize lots of different use cases, but especially in business workflows requirements where the customers want to simplify and automate their processes, the implementation of the custom post functions is necessary.