Forums

Articles
Create
cancel
Showing results for 
Search instead for 
Did you mean: 

Problems with issue linking between instances because of non serializable user object

Christof Hurst September 28, 2018

Hello,

I have to create and link issues between two Jira instances (JSD -> Jira Software).

The way of linking is very complicated and I got the script from vendor. This only works for admins and now I'm stuck with adapting it to simulate an admin user while executing.

Hope somebody can help with this.

Actual error:

2018-10-01 09:51:58,507 ERROR [workflow.ScriptWorkflowFunction]: Script function failed on issue: OCP-386, actionId: 81, file: <inline script>
io.remotecontrol.RemoteControlException: Your permission is required to make this request using RemoteControl, go to: https://support.xxxx.com/plugins/servlet/applinks/oauth/login-dance/authorize?applicationLinkID=f9ce9dd7-5c8b-3cb9-9319-xxx to create an access token
	at com.onresolve.scriptrunner.remote.AppLinkHttpTransport.send(AppLinkHttpTransport.groovy:84)
	at io.remotecontrol.client.RemoteControlSupport.sendCommandChain(RemoteControlSupport.java:43)
	at io.remotecontrol.client.RemoteControlSupport.send(RemoteControlSupport.java:38)
	at io.remotecontrol.groovy.client.RemoteControl.exec(RemoteControl.java:41)
	at io.remotecontrol.groovy.client.RemoteControl.exec(RemoteControl.java:34)
	at Script199.run(Script199.groovy:106)

Thanks in advance.

import groovy.json.JsonSlurper;
import groovy.json.StreamingJsonBuilder;
import org.apache.commons.codec.binary.Base64;
import com.atlassian.applinks.api.ApplicationLinkService
import com.atlassian.applinks.api.ApplicationLink
import com.atlassian.applinks.api.application.jira.JiraApplicationType
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.crowd.embedded.api.User
import com.atlassian.jira.bc.issue.link.RemoteIssueLinkService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.link.RemoteIssueLink
import com.atlassian.jira.issue.link.RemoteIssueLinkBuilder
import com.onresolve.scriptrunner.remote.RemoteControl
import groovy.json.JsonOutput
import org.apache.log4j.Logger

def log = Logger.getLogger("com.onresolve.scriptrunner.runner.ScriptRunnerImpl")

def jsonSlurper = new JsonSlurper()
def customFieldManager = ComponentAccessor.getCustomFieldManager()

// Get field values to transfer
def localJiraName = "xxx JIRA ServiceDesk"
def remoteJiraName = "xxx: Issuetracker"
def projectKey = "xxx"
def issueType = "Bug"
def remoteAdminUser = "ci.user"

def summary = issue.summary
def description = issue.description ?: ""
def reporter = issue.assignee
def priority = issue.getPriorityObject()
def label = issue.key
def subCategory = issue.getCustomFieldValue(customFieldManager.getCustomFieldObjectByName("Sub Category"))
def deliveredFactory = issue.getCustomFieldValue(customFieldManager.getCustomFieldObjectByName("Delivered Factory"))
def supplier = issue.getCustomFieldValue(customFieldManager.getCustomFieldObjectByName("xxx Supplier Number"))
def email = issue.getCustomFieldValue(customFieldManager.getCustomFieldObjectByName("Email"))

def body_req = [
"fields":
["project" : ["key" : projectKey],
"summary" : summary,
"description" : description,
"issuetype" : ["name": issueType],
"labels" : [label],
"reporter" : reporter,
"priority" : priority,
"customfield_15102": email,
"customfield_10201": supplier,
"customfield_38704": subCategory.toString(),
"customfield_13719": deliveredFactory.toString()
]
]

log.info("JSON input: " + JsonOutput.toJson(body_req))

//Create Index with Jiraticket Name
def baseUrl = "https://issuetracking.xxx.com"
def baseRestURL = baseUrl + "/rest/api/2/issue/"
def localUrl = "https://support.xxx.com"
def auth = "xxx"
URL url

url = new URL(baseRestURL)
HttpURLConnection connection = url.openConnection() as HttpURLConnection;
connection.requestMethod = "POST"
connection.doOutput = true
connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8")
connection.setRequestProperty("Authorization", auth)
connection.outputStream.withWriter("UTF-8") { new StreamingJsonBuilder(it, body_req) }
connection.connect();

def newIssueKey = null
log.info("Response Code: " + connection.getResponseCode())
log.info("Response Body: " + connection.getResponseMessage())

if (200 <= connection.getResponseCode() && connection.getResponseCode() <= 299) {
def br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
def responseJson = jsonSlurper.parseText(br.getText())
newIssueKey = responseJson.key

def localJiraIssueKey = issue.key
def remoteJiraIssueKey = newIssueKey

def jiraAuthenticationContext = ComponentAccessor.getJiraAuthenticationContext()
ApplicationUser originalUser = jiraAuthenticationContext.getLoggedInUser()

// def userManager = ComponentAccessor.getUserManager()
// ApplicationUser tmpAdminUser = userManager.getUserByName("ci.user")

// User adminUser = tmpAdminUser instanceof ApplicationUser ? ((ApplicationUser) tmpAdminUser).getDirectoryUser() : (User) tmpAdminUser

try {
jiraAuthenticationContext.setLoggedInUser(ComponentAccessor.getUserManager().getUserByName(remoteAdminUser))

//STEP ONE: Get application link to remote JIRA
def localJiraApplicationLinkService = ComponentAccessor.getComponent(ApplicationLinkService)
def localJiraAppLinks = localJiraApplicationLinkService.getApplicationLinks(JiraApplicationType)
def localJiraAppLinkForRemoteJira = localJiraAppLinks.find { appLink ->
appLink.name == remoteJiraName
}

def localJiraIssueId = issue.id

//STEP TWO: Use ScriptRunner RemoteControl to control remote JIRA
def remoteJiraIssueId = RemoteControl.forAppLink(localJiraAppLinkForRemoteJira).exec {

//STEP THREE: Using RemoteControl, get application link back to local JIRA
def remoteJiraApplicationLinkService = ComponentAccessor.getComponent(ApplicationLinkService)
def remoteJiraAppLinks = remoteJiraApplicationLinkService.getApplicationLinks(JiraApplicationType)
def remoteJiraAppLinkForLocalJira = remoteJiraAppLinks.find { appLink ->
appLink.name == localJiraName
}

//STEP FOUR: Using RemoteControl, create remote issue link on remote issue, on remote JIRA, linking back to local issue, on local JIRA
def remoteJiraIssue = ComponentAccessor.issueManager.getIssueByCurrentKey(remoteJiraIssueKey)
def remoteJiraLinkBuilder = new RemoteIssueLinkBuilder()

remoteJiraLinkBuilder.globalId("appId=" + remoteJiraAppLinkForLocalJira.id + "&issueId=" + localJiraIssueId)
remoteJiraLinkBuilder.issueId(remoteJiraIssue.id)
remoteJiraLinkBuilder.applicationName(remoteJiraAppLinkForLocalJira.name)
remoteJiraLinkBuilder.applicationType(RemoteIssueLink.APPLICATION_TYPE_JIRA)
remoteJiraLinkBuilder.relationship("blocks")
remoteJiraLinkBuilder.url("${remoteJiraAppLinkForLocalJira.displayUrl}/browse/${localJiraIssueKey}")
remoteJiraLinkBuilder.title(localJiraIssueKey)

def remoteJiraRemoteIssueLinkService = ComponentAccessor.getComponent(RemoteIssueLinkService)
def remoteJiraValidationResult = remoteJiraRemoteIssueLinkService.validateCreate(ComponentAccessor.getUserManager().getUserByName(remoteAdminUser), remoteJiraLinkBuilder.build())

if (remoteJiraValidationResult.isValid()) {
remoteJiraRemoteIssueLinkService.create(ComponentAccessor.getUserManager().getUserByName(remoteAdminUser), remoteJiraValidationResult)
// log.debug "Link created on remote Jira issue, for local Jira issue"
}
else {
// log.error remoteJiraValidationResult.errorCollection.errorMessages
}
return remoteJiraIssue.id
}
//STEP FIVE: Finally, create remote issue link on local issue, on local JIRA, linking to remote issue, on remote JIRA
def localJiraLinkBuilder = new RemoteIssueLinkBuilder()

localJiraLinkBuilder.globalId("appId=" + localJiraAppLinkForRemoteJira.id + "&issueId=" + remoteJiraIssueId)
localJiraLinkBuilder.issueId(localJiraIssueId)
localJiraLinkBuilder.applicationName(localJiraAppLinkForRemoteJira.name)
localJiraLinkBuilder.applicationType(RemoteIssueLink.APPLICATION_TYPE_JIRA)
localJiraLinkBuilder.relationship("is blocked by")
localJiraLinkBuilder.url("${localJiraAppLinkForRemoteJira.displayUrl}/browse/${remoteJiraIssueKey}")
localJiraLinkBuilder.title(remoteJiraIssueKey)

def localJiraRemoteIssueLinkService = ComponentAccessor.getComponent(RemoteIssueLinkService)
def localJiraValidationResult = localJiraRemoteIssueLinkService.validateCreate(ComponentAccessor.getUserManager().getUserByName(remoteAdminUser), localJiraLinkBuilder.build())

if (localJiraValidationResult.isValid()) {
localJiraRemoteIssueLinkService.create(ComponentAccessor.getUserManager().getUserByName(remoteAdminUser), localJiraValidationResult);
// log.debug "Link created on local Jira issue, for remote Jira issue"
}
else {
// log.error localJiraValidationResult.errorCollection.errorMessages
}
}
finally {
jiraAuthenticationContext.setLoggedInUser(originalUser)
}

} else {
def br = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
log.error br.getText()
}

//log.info("Create Json: " + JsonOutput.toJson(body_req))
log.info("Orig Issue: " + issue.key)
log.info("New Issue: " + newIssueKey)

0 answers

Suggest an answer

Log in or Sign up to answer