Page History
...
Code Block | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
if(firstSync){ // Set type name from source entity, if not found set a default workItem.projectKey = "Mathieu" def typeMap = [ "Epic" : "Epic", "Story" : "User Story" ] workItem.typeName = nodeHelper.getIssueType(typeMap[replica.type?.name],workItem.projectKey)?.name ?: "Task" workItem.summary = replica.summary store(issue) } if(workItem.typeName == "Task"){ workItem.summary = replica.summary workItem.description = replica.description workItem.attachments = attachmentHelper.mergeAttachments(workItem, replica) workItem.comments = commentHelper.mergeComments(workItem, replica) workItem.labels = replica.labels workItem.priority = replica.priority } def getCurrentSprint = { -> replica."Sprint".find {!it.state.equalsIgnoreCase("CLOSED")} } if (replica.customFields."Sprint"?.value != null && !replica.customFields."Sprint"?.value?.empty && getCurrentSprint() != null) { def project = connection.trackerSettings.fieldValues."project" def area = workItem.areaPath ?: workItem.project?.key ?: project def sprint = getCurrentSprint() def iteration = sprint.name def iterationPath = area + "\\" + iteration if (iterationPath != workItem.iterationPath) { def adoClient = new AdoClient(httpClient, nodeHelper, debug) def encode = { str -> if (!str) str else java.net.URLEncoder.encode(str, java.nio.charset.StandardCharsets.UTF_8.toString()) } def projectName = workItem.project?.key ?: workItem.projectKey def existingIterations = adoClient .http ( "GET", "/${encode(projectName)}/_apis/wit/classificationnodes/Iterations".toString(), ["api-version":["5.0"], "\$depth":["1"]], null, ["Accept":["application/json"]] ) { res -> if(res.code >= 400) debug.error("Failed to GET /${encode(projectName)}/_apis/work/teamsettings/iterations?api-version=7.1-preview.1 RESPONSE: ${res.code} ${res.body}") else (new groovy.json.JsonSlurper()).parseText(res.body) } ?.children if (!existingIterations.name.any {it.equalsIgnoreCase(sprint.name)}) { //if we need to create iterations def await = { f -> scala.concurrent.Await$.MODULE$.result(f, scala.concurrent.duration.Duration.apply(1, java.util.concurrent.TimeUnit.MINUTES)) } def creds = await(httpClient.azureClient.getCredentials()) def token = creds.accessToken() def baseUrl = creds.issueTrackerUrl() def dateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") def createIterationBody = [name:sprint.name] def attributes = null if(sprint.startDate) { def sd = dateFormat.format(sprint.startDate) attributes = ["startDate":sd] } if(sprint.endDate) { def ed = dateFormat.format(sprint.endDate) attributes = attributes ?: [:] attributes."finishDate" = ed } if(attributes != null) { createIterationBody."attributes" = attributes } def remoteIterationName = sprint.name def iterationId = adoClient .http ( "POST", "/${encode(projectName)}/_apis/wit/classificationnodes/Iterations".toString(), ["api-version":["5.0"]], groovy.json.JsonOutput.toJson(["name": remoteIterationName]), ["Accept":["application/json"], "Content-Type":["application/json"]] ) { res -> if(res.code >= 400) debug.error("POST ${encode(projectName)}/_apis/wit/classificationnodes/Iterations?api-version=5.0 failed: ${res.code} ${res.body}") else (new groovy.json.JsonSlurper()).parseText(res.body) }?."identifier" //and associate it with the team adoClient .http ( "POST", "/${encode(projectName)}/_apis/work/teamsettings/iterations".toString(), ["api-version":["7.1-preview.1"]], groovy.json.JsonOutput.toJson(["id": iterationId]), ["Accept":["application/json"], "Content-Type":["application/json"]] ) { res -> if(res.code >= 400) debug.error("POST ${encode(projectName)}/_apis/work/teamsettings/iterations failed: ${res.code} ${res.body}") else (new groovy.json.JsonSlurper()).parseText(res.body) } } workItem.iterationPath = iterationPath } } class AdoClient { // 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 def getGeneralSettings() { def gsOptFuture = nodeHelper.azureClient.generalSettingsService.get() def gsOpt = await(gsOptFuture) 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 private static nodeHelper private debug 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 } } AdoClient(httpClient, nodeHelper, debug) { this.httpClient = httpClient this.nodeHelper = nodeHelper this.debug = 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) //debug.error("#debug ${sanitizedUrl}") def response try { def request = ({ try { httpClient.azureClient } catch (e) { httpClient.issueTrackerClient } })() .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 credentials = await(httpClient.azureClient.credentials) def token = credentials.accessToken //debug.error("${play.api.libs.ws.WSAuthScheme$.class.code}") request = request.withAuth(token, token, play.api.libs.ws.WSAuthScheme$BASIC$.MODULE$) 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 } } } |
Here is a video;
Widget Connector | ||
---|---|---|
|
Thank you and happy exalating.
...