I'm trying to create an issue, issuelink and copy attachment from triggered issue at the same time using scriptrunner.
For now, the code below are able to create issue and attachment, but I can not link the issue I created, does someone ever deal with this situation?
import org.apache.http.entity.ContentType;
def issueKey = issue.key
def result = get('/rest/api/2/issue/' + issueKey)
.header('Content-Type', 'application/json')
.asObject(Map)
def projectkey = "PILOTLV"
if (result.body.fields.customfield_10078.id == "10124"){
projectkey = "SPCLRQ"
}
def issuetypekey = "10018"
def ticketno = result.body.fields.customfield_10060
if (result.body.fields.issuetype.id == "10015"){
issuetypekey = "10017"
ticketno = result.body.fields.customfield_10059
}
def description = result.body.fields.description
def summary = result.body.fields.summary
def sysname = result.body.fields.customfield_10078.id
logger.info(description)
logger.info(summary)
logger.info(sysname)
logger.info(ticketno)
// create issue
def createReq = Unirest.post("/rest/api/2/issue")
.header("Content-Type", "application/json")
.body([
fields: [
summary : summary,
description: description,
customfield_10078: [
id: sysname
],
customfield_10060: ticketno,
project : [
key: projectkey
],
issuetype : [
id: issuetypekey
]
],
update: [
issuelinks: [
add: [
type:[
name: "Blocks",
inward: "is blocked by",
outward: "blocks"
],
outwardIssue: [
key: issuekey
]
]
]
]
])
.asObject(Map)
assert createReq.status >= 200 && createReq.status < 300
def clonedIssue = createReq.body
// copy attachments
if (issue.fields.attachment) {
issue.fields.attachment.collect { attachment ->
def url = attachment.content as String
url = url.substring(url.indexOf("/secure"))
def fileBody = Unirest.get("${url}").asBinary().body
def resp = Unirest.post("/rest/api/2/issue/${clonedIssue.id}/attachments")
.header("X-Atlassian-Token", "no-check")
.field("file", fileBody, ContentType.create(attachment['mimeType'] as String), attachment['filename'] as String)
.asObject(List)
assert resp.status >=200 && resp.status < 300
}
}
And there is a minor question, I found that the attachment name on new issue can not display Chinese character
https://community.atlassian.com/t5/Jira-questions/rest-api-3-issue-issue-key-attachments-upload-file-with-a/qaq-p/1070389\
Looks like I'm missing library
Simply put, you can't create and link an issue via the REST API at the same time. You have to create the issue first, then link the issue separately.
Related
I'm writing some rules and learning Starlark as I progress.
Assume I have my own provider:
ModularResources = provider(
doc = "Modular resources",
fields = {
"artifactId": "Former Maven artifact id (don't ask me why)",
"srcs": "List of labels (a glob(..) thing)",
},
)
def _modular_resources_impl(ctx):
return ModularResources(
artifactId = ctx.attr.artifactId,
srcs = ctx.attr.srcs,
)
modular_resources = rule(
implementation = _modular_resources_impl,
attrs = {
"artifactId": attr.string(
mandatory = True,
),
"srcs": attr.label_list(
allow_files = True,
mandatory = True,
),
},
)
Then I have a generator rule which requires these:
some_generator = rule(
attrs = {
"deps": attr.label_list(
providers = [ ModularResources ]
),
...
},
...
)
In my implementation I discovered that I need to do a couple of unwraps to get the files:
def _get_files(deps):
result = []
for dep in deps:
for target in dep[ModularResources].srcs:
result += target.files.to_list()
return result
Is there a more efficient way to perform the collection?
As to why I'm doing this, the generator actually needs a special list of files like this:
def _format_files(deps):
formatted = ""
for dep in deps:
for target in dep[ModularResources].srcs:
formatted += ",".join([dep[ModularResources].artifactId + ":" + f.path for f in target.files.to_list()])
return formatted
FWIW, here is an example how this is used:
a/BUILD:
modular_resources(
name = "generator_resources",
srcs = glob(
["some/path/**/*.whatever"],
),
artifactId = "a",
visibility = ["//visibility:public"],
)
b/BUILD:
some_generator(
name = "...",
deps = [
"//a:generator_resources"
]
)
If you want to trade memory for better performance, maybe the operation can more easily be parallelised by blaze if it's done in the provider instead:
def _modular_resources_impl(ctx):
return ModularResources(
artifactId = ctx.attr.artifactId,
formatted_srcs = ",".join([artifactId + ":" + f.path for f in ctx.files.src])
)
I've got a JSON file that I am slurping with groovy.
{
"team": "${GLOBAL_TEAM_NAME}",
"jobs": [
{
In the JSON above is a property 'team' that contains a groovy-like variable I want to be resolved at runtime.
teamList.each { tl ->
try
{
def teamSlurper = new JsonSlurperClassic()
def t = teamSlurper.parseText(tl.text)
println "*********************"
println "PROVISIONING JOB FOR: " + t.team
Output:
PROVISIONING JOB FOR: ${GLOBAL_TEAM_NAME}
The above outputs the raw value, but I would like it to resolve the global variable that has been defined for the system.
How can I resolve ${GLOBAL_TEAM_NAME} to its actual system value?
You can do this with Groovy Templates.
def slurper = new groovy.json.JsonSlurperClassic()
def engine = new groovy.text.SimpleTemplateEngine()
def binding = ["GLOBAL_TEAM_NAME": "Avengers"]
def json = '{"team":"${GLOBAL_TEAM_NAME}"}'
def t = slurper.parseText(engine.createTemplate(json).make(binding).toString())
t.team // "Avengers"
I am trying to build a json request in SoapUI and trying to post to a test step. For building the request, I have below code. When I execute it, it is throwing a JsonException (text provided below.) Any advise would be greatly appreciated. I have done this for over 60 services (so I've done this a 1001 times) and all of them have passed/worked. I am unable to pinpoint as to what the issue here is. Thanks!
import groovy.json.JsonSlurper
import groovy.json.JsonOutput
def setReqPayload ( pArrKeyValues ) {//[objId, dirInd, selActId, actDt, coType, secId]
def jsonPayload = '''
{
"objectId" : "",
"actDate": "",
"dirIndicator" : "",
"selectActId" : "",
"coInfo" : {"secId" : "","coType" : ""}
}
'''
// parse the request
def jsonReq = new JsonSlurper ( ).parseText ( jsonPayload )
jsonReq.objectId = pArrKeyValues [ 0 ] )
jsonReq.dirIndicator = pArrKeyValues [ 1 ]
jsonReq.selectActId = pArrKeyValues [ 2 ]
jsonReq.actDate = pArrKeyValues [ 3 ]
jsonReq.coInfo.coType = pArrKeyValues [ 4 ]
jsonReq.coInfo.secId = pArrKeyValues [ 5 ]
log.info "REQUEST JSON SLURP: " + jsonReq
return jsonReq
}
Exception:
ERROR:groovy.json.JsonException: expecting '}' or ',' but got current char ' ' with an int value of 160 The current character read is ' ' with an int value of 160
I have used below code as well to parse but that is throwing different kind of exception (Not that kind of map) and not allowing me to set the values to the keys.
// parse the request
def parser = new JsonSlurper ( ).setType ( JsonParserType.LAX )
def jsonReq = JsonOutput.toJson ( parser.parseText ( jsonPayload ) )
You have non-breaking space character(s) in your JSON, it's unfortunately invalid, it should be the usual space character.
Using LAX mode was a good idea but it does not seem to handle non-breaking spaces:
Use LAX if you want to enable relaxed JSON parsing, i.e., allow
comments, no quote strings, etc.
So if you cannot clean up your data at the source, you can filter it like this:
jsonPayload = jsonPayload.replace('\u00a0', '\u0020')
Looks like you have some trivial issue in the script.
Below script:
import groovy.json.JsonSlurper
import groovy.json.JsonOutput
def setReqPayload ( pArrKeyValues ) {//[objId, dirInd, selActId, actDt, coType, secId]
def jsonPayload = '''
{
"objectId" : "",
"actDate": "",
"dirIndicator" : "",
"selectActId" : "",
"coInfo" : {"secId" : "","coType" : ""}
}
'''
// parse the request
def jsonReq = new JsonSlurper ( ).parseText ( jsonPayload )
jsonReq.objectId = pArrKeyValues [ 0 ]
jsonReq.dirIndicator = pArrKeyValues [ 1 ]
jsonReq.selectActId = pArrKeyValues [ 2 ]
jsonReq.actDate = pArrKeyValues [ 3 ]
jsonReq.coInfo.coType = pArrKeyValues [ 4 ]
jsonReq.coInfo.secId = pArrKeyValues [ 5 ]
println "REQUEST JSON SLURP: " + jsonReq
return jsonReq
}
setReqPayload([1,2,3,4,5,6])
Produces below output:
{actDate=4, coInfo={coType=5, secId=6}, dirIndicator=2, objectId=1, selectActId=3}
I am trying to post data to an API, the API is requesting a JSON request as this:
{
"blacklists": {
"list1": [{
"id": "123",
"find": "foo",
"type": "text"
}],
"list2": [{
"id": "321",
"find": "bar",
"type": "text"
}]
}
}
My problem is building a JSON with hash and arrays representing the above.
This is the code I have so far:
#blacklist = {}
#bl = {}
key_category = KeywordCategory.where("global_list = ? OR unit_id = ?",1,1)
key_category.each do |kc|
bl_name = kc.name # <- "list1, list2 etc."
kc.keywords.each do |kw|
#keywords = {}
#keywords['id'] = kw.id
#keywords['find'] = kw.data
#keywords['type'] = kw.is_regexp ? "regexp" : "text"
#bl.merge!(#keywords)
end
end
#blacklist['blacklist'] = #bl
return #blacklist.to_json
This code gives me this JSON (which is a bit from the one the API wants):
{
"blacklists":
{"id":123,
"find":"foo",
"type":"text"
}
}
How do I change my code so it spits out according to the top JSON?
Try something like this:
#blacklist = {}
#bl = {}
key_category = KeywordCategory.where("global_list = ? OR unit_id = ?",1,1)
key_category.each do |kc|
tmparray = []
kc.keywords.each do |kw|
#keyword = { id: kw.id, find: kw.data, type: kw.is_regexp ? 'regexp' : 'text" }
tmparray << #keyword
end
#bl.merge!(kc.name: tmparray)
end
#blacklist['blacklist'] = #bl
return #blacklist.to_json
During my internship I needed to work on an existing ruby on rails project.
This project is built with spree. The developers before my tweaked the price filter so that the range would change to to max of the products of that taxon.
Here by the code of "lib/spree/core/product_filter.rb"
Spree::Product.add_search_scope :price_range_any do |*opts|
opts_arr, max_prod, min_prod = [], nil, nil
opts.each do |opt|
tmp_arr = opt.split("+")
opts_arr << tmp_arr[0]
max_prod = tmp_arr[1]
min_prod = tmp_arr[2]
end
conds = opts_arr.map {|o| Spree::Core::ProductFilters.price_filter(max_prod.to_i, min_prod.to_i)[:conds][o]}.reject { |c| c.nil? }
scope = conds.shift
conds.each do |new_scope|
scope = scope.or(new_scope)
end
Spree::Product.joins(master: :default_price).where(scope)
end
def ProductFilters.format_price(amount)
Spree::Money.new(amount)
end
def ProductFilters.price_filter(max_price = nil, min_price = nil)
v = Spree::Price.arel_table
if max_price < 200
if max_price < 100
highest_price = max_price - max_price.modulo(10)
else
highest_price = max_price - max_price.modulo(25)
end
interval = (highest_price)/5
second = interval + interval
third = second + interval
conds = [ [ "#{format_price(0)} - #{format_price(interval)}" , v[:amount].in(0..interval)],
[ "#{format_price(interval)} - #{format_price(second)}" , v[:amount].in(interval..second)],
[ "#{format_price(second)} - #{format_price(third)}" , v[:amount].in(second..third)],
[ "#{format_price(third)} - #{format_price(highest_price)}" , v[:amount].in(third..highest_price)],
[ Spree.t(:or_over_price, price: format_price(highest_price)) , v[:amount].gteq(highest_price)]]
{
name: Spree.t(:price_range),
scope: :price_range_any,
conds: Hash[*conds.flatten],
labels: conds.map { |k,v| [k, k] }
}
else
conds = [ [ "#{format_price(0)} - #{format_price(50)}" , v[:amount].in(0..50)],
[ "#{format_price(50)} - #{format_price(100)}" , v[:amount].in(50..100)],
[ "#{format_price(100)} - #{format_price(150)}" , v[:amount].in(100..150)],
[ "#{format_price(150)} - #{format_price(200)}" , v[:amount].in(150..200)],
[ Spree.t(:or_over_price, price: format_price(200)) , v[:amount].gteq(200)]]
{
name: Spree.t(:price_range),
scope: :price_range_any,
conds: Hash[*conds.flatten],
labels: conds.map { |k,v| [k, k] }
}
end
end
It is working, in the price range filter the range changed when the max price went up but the filter doesn't filter the products.
I tried everything I know so far of ruby on rails but nothing seem to be helping. Example when I comment key value of the add_search_scope out nothing changes.
Can you please tell me whats going wrong?