Skip to main content
High speed issue linking in Jira Service Management
Share on socials
Illustration of issues being prioritised in Jira
Phill Fox
Phill Fox
6th November, 2018
Jira

High speed issue linking in Jira Service Management

Issue linking in Jira Service Desk helps you deal with issues quicker. Learn how to link Incidents, Alerts & Remedial Actions to current or recent problems.
Automating Incident Management not only makes your Incident resolution quicker and your customers happier, but reduces the risk of errors under stress. Let's look at how you can link your Incidents, Alerts and Remedial Actions to current and recent Problems, using a self-referencing transition in your Jira workflow.
This post covers linking related Issues together for better diagnostics and management.
In order to create this functionality, we need to reuse some configurations that are discussed in other articles. If you haven't read these yet, start there.
Let's quickly recap on what we covered in these two articles and what we'll reuse.
In this blog on Adaptavist.com, we created new Issuetypes and established appropriate links between them. We'll be using both the Issuetypes and links for this functionality.
In this blog, we saw how we could use JQL to find unresolved and recently-resolved problems. We will be reusing the following JQL to restrict our selection to current and recent Problem Issuetypes.
Note: If you've given different names to your Issuetypes or links, you will need to update the code that follows to match.

What linking achieves

Linking related Issues together is a powerful feature of Jira which allows you to better diagnose Issues and manage your work. If you're a frequent Jira user, you would have likely linked Issues before and have probably found it to be manual and labour-intensive. A process that requires you to know exactly what Issues should be linked and to manually complete forms.
What if we could speed up this process and reduce the potential for Issues to be missed or incorrectly connected?

Linking the problem ticket

The first step in linking tickets is to create a custom field. This custom field needs to be set as a Hideable Text Field and labeled as "Known Problem". To build this Hideable Text Field select the <255 characters option in the Advanced Select Field Type. We're selecting this option as we only need to store the Problem Issue key in the field which should never be anywhere near 255 characters in length.
Screenshot of the linked ticket
Next, we want to make sure that this field is only available for the following Issuetypes Incident, Alert, Remedial Action. This means that we need to set the configuration to only these three Issuetypes. At this stage, we could also restrict this functionality to certain projects but for this example, we're only restricting our use of the Issuetypes with an Issuetype Scheme at the project level.
Screenshot of custom field configuration
Now we have the custom field, we will create a screen called “Link to recent Problem” that we can use on the transition. For this screen, we are going to keep the information requested to the Known Problem field that we have just created and of course the standard comment field.

Updating your workflow

After we've added our screen, the next step is to edit the workflow(s) that are associated with the Issuetypes Incident, Alert, and Remedial Action. We're going to use a little-known but powerful piece of functionality, the ability for a workflow to transition from any status back to the same status. While adding a circular workflow sounds rather odd, critically it allows us to add a transition and where you have a transition you can add a transition screen and post-function. This appears on the workflow diagram as shown.
Circular workflow icon

Creating a transition

So let's look at the steps to create this transition. First, we'll add a transition and fill in the options as shown below.
Screenshot of adding a new transition
Note: The two status fields use special values that don't refer to the single status.
After that, we need to add the following condition to the workflow to make sure this is only available for the appropriate Issuetypes.
Screenshot of a workflow condition
We could also add a property to the transition to place the transition as the first option.
Screenshot of a transition property
The final step in the workflow stage is to publish it. Once we've done this, remember to check that the right screen loads on the transition.

Adding behaviours

Our next step is to add the behaviour to our new field so that it only offers the choices from current or recent Problems. In order to add the behaviour navigate to:
<yourhost>/secure/admin/Behaviours!default.jspa
Select create a new behaviour and give your new behaviour the following name and description:
Behaviour name and description
Then map the following fields:
Field mapping details
Next, add an initialiser function with the following code. This initialiser function will be called whenever the field is presented on a screen for editing.
1getFieldByName("Known Problem").convertToSingleSelect([
2ajaxOptions: [
3url : getBaseUrl() + "/rest/scriptrunner-Jira/latest/issue/picker",
4query: true, // keep going back to the sever for each keystroke
5// this information is passed to the server with each keystroke
6data: [
7currentJql: "issuetype=Problem AND (resolution is EMPTY OR resolutiondate > -7d) ORDER BY resolution, key ASC",
8label : "Pick from Open or Recent Problems",
9showSubTasks: false,
10// specify maximum number of issues to display, defaults to 10
11max: 5,
12],
13formatResponse: "issue"
14],
15//Specify css for the size of the dropdown maximum width
16css: "max-width: 500px; width: 500px",
17]
18)
Lastly, place a listener on the custom field in order to make sure that whenever a value is entered the links on the issue are updated to include the related Problem.
1import com.atlassian.Jira.bc.issue.link.IssueLinkService 
2import com.atlassian.Jira.component.ComponentAccessor
3import com.atlassian.Jira.issue.Issue
4import com.atlassian.Jira.issue.link.Direction
5import com.atlassian.Jira.issue.link.IssueLinkTypeManager
6import com.atlassian.Jira.user.ApplicationUser
7
8// Constants
9final PROBLEM_FIELD = "customfield_10501" 
10final INCIDENT_LINK = "Incident Link" 
11final ALERT_LINK = "Alert Link" 
12final REMEDIAL_LINK = "Remedial Action Link" 
13
14def createIssueLink(Issue startIssue, 
15Issue issueToLink, 
16Long linkTypeId, 
17Direction linkDirection, 
18ApplicationUser updateUser) { 
19
20// Get the issue service
21final issueLinkService = ComponentAccessor.getComponent(IssueLinkService)
22
23// Validate the link creation
24final addIssueLinkValidationResult =
25issueLinkService.validateAddIssueLinks(updateUser,
26startIssue, 
27linkTypeId, 
28linkDirection, 
29[issueToLink.key], 
30true) 
31
32// Create the actual link 
33if (addIssueLinkValidationResult.valid) { 
34issueLinkService.addIssueLinks(updateUser, addIssueLinkValidationResult)
35}
36}
37
38List<Issue> getLinkedIssues(Issue rootIssue, 
39String linkType) { 
40
41// Managers
42final issueLinkManager = ComponentAccessor.issueLinkManager
43
44// The list to hold our found issues 
45def outIssues = [] 
46
47// Get the outward links of the issue and find the matching ones
48final outwardLinks = issueLinkManager.getOutwardLinks(rootIssue.id) 
49final foundOutLinks = outwardLinks.findAll { 
50it.issueLinkType.name in linkType
51}
52
53// Find the linked issues and return
54foundOutLinks.each{outIssues.add(it.destinationObject)} 
55return outIssues 
56}
57
58// Managers
59final customFieldManager = ComponentAccessor.customFieldManager 
60final issueManager = ComponentAccessor.issueManager 
61final linkTypeManager = ComponentAccessor.getComponent(IssueLinkTypeManager)
62final authContext = ComponentAccessor.JiraAuthenticationContext 
63
64// Get the issue from the event and get the value of the field
65final issue = event.issue 
66final customField = customFieldManager.getCustomFieldObject(PROBLEM_FIELD)
67final issueFieldValue = customField.getValue(issue) as String
68
69//Create a variable to hold the appropriate link depending on whether the current issue is an incident or an aler 
70
71def PROBLEM_LINK = "" 
72if(issue.getIssueType().getName() == "Incident"){ 
73PROBLEM_LINK = INCIDENT_LINK
74}else if(issue.getIssueType().getName() == "Alert"){
75PROBLEM_LINK = ALERT_LINK
76}else if(issue.getIssueType().getName() == "Remedial Action"){ 
77PROBLEM_LINK = REMEDIAL_LINK
78}
79
80//If we have a Problem_Link, check for new or existing links
81if (PROBLEM_LINK != "") {
82// If the customfield has a value, do something
83if ( issueFieldValue) { 
84
85// Get all the linked issues and exit if the issue is already one
86final linkedIssues = getLinkedIssues(issue, PROBLEM_LINK).collect{it.key}
87if (issueFieldValue in linkedIssues) {return} 
88
89// Get the bits we need for the link 
90final currentUser = authContext.loggedInUser
91final issueLink = linkTypeManager.getIssueLinkTypesByName(PROBLEM_LINK).first() 
92final linkIssue = issueManager.getIssueByCurrentKey(issueFieldValue) 
93
94// Make the link
95createIssueLink(issue, linkIssue, issueLink.id, Direction.OUT, currentUser)
96}
97}

Testing the link

You should now test that your system is working and that when a new Known Problem is associated with an Incident, Alert or Remedial Action the Issue links are updated correctly.
Once it is, you'll be able to group your incidents with much more ease, increasing your diagnostic abilities and allowing for better organisation of your Triage.

Hungry for more incident management magic?

This post looks at how we can quickly create a new problem ticket from inside an Incident or Alert.