Export/Import Advanced Links via CSV

Jira allows import of Jira issues and subtasks via CSV.

Jira allows import of default Jira links via CSV.

Hidden links types such as epic links or asset Advanced Links cannot be imported with a single CSV import.

Workaround 1: 2 Imports and V-Lookup

(as recommended by Atlassian Community)

  1. Import issues without Advanced Links.

  2. Export imported issues with their issue keys and summary.

  3. Use excel V-Lookup to merge issue keys into original csv file for every row and for the links to be imported (see docu).

  4. Import csv again to update issue links for existing issues (map issue key as well to avoid creation of issue duplicates).

Workaround 2: Scripted post-function

(as recommended by STAGIL using Script Runner or Power Scripts)

  1. Import issues with epic links and Advanced Links as default links (i.e. relates to).

  2. Allow users to change link types in bulk change via workflow transition with a scripted post-function. Show this option only to issues that have issue links of defined link type.
    The following scripts allow defining link type per issue type. I.e. you can configure a different target parent link for issues of type “Story” than for issues of type “Epic”.

Workflow Post-function Groovy Script

import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.event.type.EventDispatchOption def issueManager = ComponentAccessor.getIssueManager() def customFieldManager = ComponentAccessor.getCustomFieldManager() def issueLinkManager = ComponentAccessor.getIssueLinkManager() def jiraAuthenticationContext = ComponentAccessor.getJiraAuthenticationContext() def currentUser = jiraAuthenticationContext.getLoggedInUser() def issueLinkID def SAJfieldID if (issue.getIssueType().name == "Epic") { issueLinkID = 12345 as Long SAJfieldID = 11000 as Long } else if (issue.getIssueType().name == "Story" || issue.getIssueType().name == "Bug" || issue.getIssueType().name == "Task") { issueLinkID = 13579 as Long SAJfieldID = 11200 as Long } else { return } def existingLinks = issueLinkManager.getIssueLinks(issueLinkID).findAll() { it.sourceId == issue.id } //sourceId, wenn Outward-Link; destinationId, wenn Inward-Link (Vorgang dient als Ausgangspunkt) def SAJfield = customFieldManager.getCustomFieldObject(SAJfieldID) for (existingLink in existingLinks) { def destinationIssueId = existingLink.destinationId as Long //destinationId, wenn Outward-Link; sourceId, wenn Inward-Link (Vorgang dient als Ziel des Links) def destinationIssue = issueManager.getIssueObject(destinationIssueId) def destinationIssueKey = destinationIssue.key as String if (destinationIssue.getIssueType().name == "Epic" && (issue.getIssueType().name == "Story" || issue.getIssueType().name == "Bug" || issue.getIssueType().name == "Task")) { def newEpic = issueManager.getIssueByCurrentKey(destinationIssueKey) def epicLinkCustomField = customFieldManager.getCustomFieldObjects(issue).findByName("Epic Link") //wenn Deutsch, dann: "Epic-Verknüpfung" issue.setCustomFieldValue(epicLinkCustomField, newEpic) } else { def SAJfieldValue = issue.getCustomFieldValue(SAJfield) as String if (SAJfieldValue == null) { issue.setCustomFieldValue(SAJfield, destinationIssueKey) } else if (!SAJfieldValue.contains(destinationIssueKey)) { issue.setCustomFieldValue(SAJfield, SAJfieldValue + ", " + destinationIssueKey) } } issueLinkManager.removeIssueLink(existingLink, currentUser) } issueManager.updateIssue(currentUser, issue, EventDispatchOption.ISSUE_UPDATED, false)

Issue link type ID (12345) to be replaced with actual ID.

SAJ field ID (11000) to be replaced with actual ID.

The above script refers to outward links only. If you want to replace inward links instead, sourceId (line 11) and destinationID (line 16) need to be swapped.

Workflow Condition Groovy Script

import com.atlassian.jira.component.ComponentAccessor def issueLinkManager = ComponentAccessor.getIssueLinkManager() def existingLinks = issueLinkManager.getIssueLinks(12345).findAll() { it.sourceId == issue.id } as boolean //sourceId, wenn Outward-Link; destinationId, wenn Inward-Link (beides nimmt aktuellen Vorgang als Ausgangspunkt) return existingLinks

Issue link type ID (12345) to be replaced with actual ID.

The above script refers to outward links only. If you want to look for inward links instead, sourceId (line 5) to be replaced with destinationId.

 

© 2023, STAGIL