Questions
1
0
-1
2 answers
- 210
Hi George Smith,
The way I have designed this use case is that with every sync transaction, Jira sends out a list of all users. Then on the ZD side, this payload is received and populated into a ZD drop down field. The scripts to be used are the following:
Jira Outgoing Expand sourcedef a = new JiraClient(httpClient).http("GET", "/rest/api/3/user/assignable/multiProjectSearch",["projectKeys":["CM"]], null, [:]) def jsonSlurper = new groovy.json.JsonSlurper() def parseText = jsonSlurper.parseText(a) def asg_list = new String[parseText.size()] def asg_email = new String[parseText.size()] for(int i=0; i<parseText.size(); i++){ if (parseText[i].displayName != null){ asg_list[i] = parseText[i].displayName asg_email[i] = parseText[i].emailAddress } } replica.assignee_list = asg_list replica.assignee_email = asg_email
Zendesk Incoming script Expand sourceclass InjectorGetter { static Object getInjector() { try { return play.api.Play$.MODULE$.current().injector() } catch (e) { def context = com.exalate.replication.services.processor.CreateReplicaProcessor$.MODULE$.threadLocalContext.get() if (!context) { context = com.exalate.replication.services.processor.ChangeIssueProcessor$.MODULE$.threadLocalContext.get() } if (!context) { context = com.exalate.replication.services.processor.CreateIssueProcessor$.MODULE$.threadLocalContext.get() } if (!context) { throw new com.exalate.api.exception.IssueTrackerException(""" No context for executing external script CreateIssue.groovy. Please contact Exalate Support.""".toString()) } context.injector } } } class ZdClient { // SCALA HELPERS private static <T> T await(scala.concurrent.Future<T> f) { scala.concurrent.Await$.MODULE$.result(f, scala.concurrent.duration.Duration$.MODULE$.Inf()) } private static <T> T orNull(scala.Option<T> opt) { opt.isDefined() ? opt.get() : null } private static <T> scala.Option<T> none() { scala.Option$.MODULE$.<T> empty() } @SuppressWarnings("GroovyUnusedDeclaration") private static <T> scala.Option<T> none(Class<T> evidence) { scala.Option$.MODULE$.<T> empty() } private static <L, R> scala.Tuple2<L, R> pair(L l, R r) { scala.Tuple2$.MODULE$.<L, R> apply(l, r) } // SERVICES AND EXALATE API private static play.api.inject.Injector getInjector() { InjectorGetter.getInjector() } private static def getGeneralSettings() { def gsp = InjectorGetter.getInjector().instanceOf(com.exalate.api.persistence.issuetracker.IGeneralSettingsRepository.class) //def gsp = InjectorGetter.getInjector().instanceOf(com.exalate.api.persistence.issuetracker.IGeneralSettingsPersistence.class) def gsOpt = await(gsp.get()) def gs = orNull(gsOpt) gs } private static String getIssueTrackerUrl() { final def gs = getGeneralSettings() def removeTailingSlash = { String str -> str.trim().replace("/+\$", "") } final def issueTrackerUrl = removeTailingSlash(gs.issueTrackerUrl) issueTrackerUrl } private httpClient def parseQueryString = { String string -> string.split('&').collectEntries { param -> param.split('=', 2).collect { URLDecoder.decode(it, 'UTF-8') } } } //Usage examples: https://gist.github.com/treyturner/4c0f609677cbab7cef9f def parseUri { parseUri = { String uri -> def parsedUri try { parsedUri = new URI(uri) if (parsedUri.scheme == 'mailto') { def schemeSpecificPartList = parsedUri.schemeSpecificPart.split('\\?', 2) def tempMailMap = parseQueryString(schemeSpecificPartList[1]) parsedUri.metaClass.mailMap = [ recipient: schemeSpecificPartList[0], cc : tempMailMap.find { it.key.toLowerCase() == 'cc' }.value, bcc : tempMailMap.find { it.key.toLowerCase() == 'bcc' }.value, subject : tempMailMap.find { it.key.toLowerCase() == 'subject' }.value, body : tempMailMap.find { it.key.toLowerCase() == 'body' }.value ] } if (parsedUri.fragment?.contains('?')) { // handle both fragment and query string parsedUri.metaClass.rawQuery = parsedUri.rawFragment.split('\\?')[1] parsedUri.metaClass.query = parsedUri.fragment.split('\\?')[1] parsedUri.metaClass.rawFragment = parsedUri.rawFragment.split('\\?')[0] parsedUri.metaClass.fragment = parsedUri.fragment.split('\\?')[0] } if (parsedUri.rawQuery) { parsedUri.metaClass.queryMap = parseQueryString(parsedUri.rawQuery) } else { parsedUri.metaClass.queryMap = null } if (parsedUri.queryMap) { parsedUri.queryMap.keySet().each { key -> def value = parsedUri.queryMap[key] if (value.startsWith('http') || value.startsWith('/')) { parsedUri.queryMap[key] = parseUri(value) } } } } catch (e) { throw new com.exalate.api.exception.IssueTrackerException("Parsing of URI failed: $uri $e ", e) } parsedUri } } ZdClient(httpClient, debug) { this.httpClient = httpClient this.debug = debug } def debug String http(String method, String path, java.util.Map<String, List<String>> queryParams, String body, java.util.Map<String, List<String>> headers) { http(method, path, queryParams, body, headers) { Response response -> if (response.code >= 300) { throw new com.exalate.api.exception.IssueTrackerException( """Failed to perform the request $method $path (status ${response.code}), and body was: ```$body``` Please contact Exalate Support: """.toString() + response.body ) } response.body as String } } public <R> R http(String method, String path, java.util.Map<String, List<String>> queryParams, String body, java.util.Map<String, List<String>> headers, Closure<R> transformResponseFn) { def gs = getGeneralSettings() def unsanitizedUrl = issueTrackerUrl + path def parsedUri = parseUri(unsanitizedUrl) def embeddedQueryParams = parsedUri.queryMap def allQueryParams = embeddedQueryParams instanceof java.util.Map ? ({ def m = [:] as java.util.Map<String, List<String>>; m.putAll(embeddedQueryParams as java.util.Map<String, List<String>>) m.putAll(queryParams) })() : (queryParams ?: [:] as java.util.Map<String, List<String>>) def urlWithoutQueryParams = { String url -> URI uri = new URI(url) new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), uri.getPath(), null, // Ignore the query part of the input url uri.getFragment()).toString() } def sanitizedUrl = urlWithoutQueryParams(unsanitizedUrl) def response try { def request = httpClient .zendeskClient .ws .url(sanitizedUrl) .withMethod(method) if (!allQueryParams.isEmpty()) { def scalaQueryParams = scala.collection.JavaConversions.asScalaBuffer( queryParams .entrySet() .inject([] as List<scala.Tuple2<String, String>>) { List<scala.Tuple2<String, String>> result, kv -> kv.value.each { v -> result.add(pair(kv.key, v) as scala.Tuple2<String, String>) } result } ) request = request.withQueryString(scalaQueryParams) } if (headers != null && !headers.isEmpty()) { def scalaHeaders = scala.collection.JavaConversions.asScalaBuffer( headers .entrySet() .inject([] as List<scala.Tuple2<String, String>>) { List<scala.Tuple2<String, String>> result, kv -> kv.value.each { v -> result.add(pair(kv.key, v) as scala.Tuple2<String, String>) } result } ) request = request.withHeaders(scalaHeaders) } if (body != null) { def writable = play.api.libs.ws.WSBodyWritables$.MODULE$.writeableOf_String() request = request.withBody(body, writable) } def authorizationHeader = await(httpClient.zendeskClient.getAuthHeaderFromGs()) request = request.addHttpHeaders(scala.collection.JavaConversions.asScalaBuffer([pair("Authorization", authorizationHeader) as scala.Tuple2<String, String>])) //debug.error("${request.method()} ${request.url()} ${request.headers()}") response = await(request.execute()) } catch (Exception e) { throw new com.exalate.api.exception.IssueTrackerException( """Unable to perform the request $method $path with body:```$body```, please contact Exalate Support: """.toString() + e.message, e ) } java.util.Map<String, List<String>> javaMap = [:] for (scala.Tuple2<String, scala.collection.Seq<String>> headerTuple : scala.collection.JavaConverters.bufferAsJavaListConverter(response.allHeaders().toBuffer()).asJava()) { def javaList = [] javaList.addAll(scala.collection.JavaConverters.bufferAsJavaListConverter(headerTuple._2().toBuffer()).asJava()) javaMap[headerTuple._1()] = javaList } def javaResponse = new Response(response.body(), new Integer(response.status()), javaMap) return transformResponseFn(javaResponse) } public static class Response { final String body final Integer code final java.util.Map<String, List<String>> headers Response(String body, Integer code, java.util.Map<String, List<String>> headers) { this.body = body this.code = code this.headers = headers } } } issue.labels = replica.labels issue.summary = replica.summary issue.description = replica.description ?: "No description" issue.attachments = attachmentHelper.mergeAttachments(issue, replica) issue.comments += replica.addedComments def mapAssignees = [[:]] for (int i=0; i<replica.assignee_list.size(); i++){ if(replica.assignee_email[i] != ""){ Map temp = [:] temp.put("name" , "${replica.assignee_list[i]}") temp.put("value" , "${replica.assignee_email[i]?.replaceAll('@', '__')}") mapAssignees[i] = temp } else { Map temp = [:] temp.put("name" , "${replica.assignee_list[i]}") temp.put("value" , "test${i}__email.com") mapAssignees[i] = temp } } Map<String,List<String>> queryParams = ["ticket_field": ["custom_field_options": mapAssignees]] def queryParamsJson = groovy.json.JsonOutput.toJson(queryParams) def res = new ZdClient(httpClient, debug) .http( "PUT", "/api/v2/ticket_fields/7309935056017", [:], "${queryParamsJson}", ["Accept": ["application/json"], "Content-type" : ["application/json"]] ) { response -> if (response.code >= 400) { throw new com.exalate.api.exception.IssueTrackerException("Failed to get orgnaizations with name ") } else response.body as String } if (replica.assignee?.email) issue.customFields."Jira Assignee".value.value = replica.assignee.email.replaceAll('@','__')
Here is a short video demonstrating the solution in action:
Thanks
Majid
CommentAdd your comment... - 10-1
Hi Majid,
I am getting an error and the list of email addresses is empty...remote replica is not showing the adresses.How to proceed at that point?
- Syed Majid Hassan
Not really, as it does not really give me much. Can you please book a slot here and we will give it another shot.
Thanks
Majid
CommentAdd your comment...
We need a user-defined drop-down field in ZD to be populated with data from all possible assignees in Jira i.e. if a new user in Jira Cloud is created and assigned an issue, this should create a new value in the ZD drop-down and populate the field with this value.