Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

need groovy script to invoke external link in post function

Hi,

I have an curl command to trigger an external url. Need some help on script runner groovy script for below command format.

curl --location --request POST 'https://XXXX.XXXX.com:443/api/1/rest/slsched/feed/XXXXXXXXXX/projects/SXXXXXX%20xxxxx/JIRA-Access-TEST%20Task' \ --header 'Authorization: Bearer xxxxxxxxxxxxxxxxxxxx' \ --header 'Content-Type: application/json' \ --data-raw '[ { "Request": { "issueKey": "JJIM-26", "issueId": "This is passthorugh response" } } ]'

 

Thanks in advance.

Regards,

Aditya.D

1 answer

1 accepted

0 votes
Answer accepted

Hi

You could execute the curl command as a shell command using the "execute()" method available on groovy strings.

def cmd = """curl --location --request POST 'https://XXXX.XXXX.com:443/api/1/rest/slsched/feed/XXXXXXXXXX/projects/SXXXXXX%20xxxxx/JIRA-Access-TEST%20Task' \ --header 'Authorization: Bearer xxxxxxxxxxxxxxxxxxxx' \ --header 'Content-Type: application/json' \ --data-raw '[ { "Request": { "issueKey": "JJIM-26", "issueId": "This is passthorugh response" } } ]'"""
def process = command.execute()
def sOut = new StringBuilder()
def sErr = new StringBuilder()
process.consumeProcessOutput(sOut,sErr)
process.waitForOrKill(60000) //milliseconds... timeout

Then you could process the sOut strings

Or you can use some native html processing classes.

import groovyx.net.http.HTTPBuilder
import groovyx.net.http.Method
import groovyx.net.http.ContentType
def httpBuilder = new HTTPBuilder(https://XXXX.XXXX.com:443)
def response = httpBuilder.request(Method.POST, ContentType.JSON){
uri.path = "/api/1/rest/slsched/feed/XXXXXXXXXX/projects/SXXXXXX%20xxxxx/JIRA-Access-TEST%20Task"
headers.Authorization = "Bearer xxxxxxxxxxxxxxxxxxxx"
body = [Request:[issueKey:"JJIM-26", issueId:""]]

response.success = { response, json ->
return json
}
response.failure = { resp, data ->
log.error " httprequest failed: $data"
return null
}
}

This will give you some native parsing of the response and response error handling etc.

Hi Peter-Dave,

Thanks for the script. 

I tried to run the first script, throwing below error:

 image.png

You can either escape the \ or change the type of groovy string. The dollar-slashy string is perfect for this use case:

(also, I had an error in the script where I called the command string "cmd" but then tried to execute as if I had called it "command"

Here it is fully corrected

def cmd = $/curl --location --request POST 'https://XXXX.XXXX.com:443/api/1/rest/slsched/feed/XXXXXXXXXX/projects/SXXXXXX%20xxxxx/JIRA-Access-TEST%20Task' \ --header 'Authorization: Bearer xxxxxxxxxxxxxxxxxxxx' \ --header 'Content-Type: application/json' \ --data-raw '[ { "Request": { "issueKey": "JJIM-26", "issueId": "This is passthorugh response" } } ]'/$
def process = cmd.execute()
def sOut = new StringBuilder()
def sErr = new StringBuilder()
process.consumeProcessOutput(sOut,sErr)
process.waitForOrKill(60000) //milliseconds... timeout
Like Aditya D likes this

Thanks again Peter-Dave for valuable script. Could you help me out with two more improvements.

1. First : "Issue key" & "issue id" has to come dynamically. I'm placing this script in post function. As soon status changed, script should pick the "issuekey" and "issuekey id" of that issue. 

2. Second :  No transaction success information on issue page. Is it possible to print transaction success code/ log info on issue page  like activity tab/history/worklog. Some where we can refer as soon as transition is completed. 

 

BR,

Aditya.D

I think given your use case, I would strongly recommend using the httpbuilder approach rather than the curl approach.

Then, with post function, there are a couple of things you can do for telling the user this took place. 

1) You can display a flag 
2) You can generate a fake history record

Here is a full example:

import com.atlassian.jira.component.ComponentAccessor
import
groovyx.net.http.HTTPBuilder
import groovyx.net.http.Method
import groovyx.net.http.ContentType
import com.onresolve.scriptrunner.runner.util.UserMessageUtil
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.issue.history.ChangeItemBean
import com.atlassian.jira.issue.history.ChangeLogUtils

def apiBase = "https://XXXX.XXXX.com:443"
def apiPath = "/api/1/rest/slsched/feed/XXXXXXXXXX/projects/SXXXXXX%20xxxxx/JIRA-Access-TEST%20Task"

def httpBuilder = new HTTPBuilder(apiBase)
def response = httpBuilder.request(Method.POST, ContentType.JSON){
uri.path = apiPath
headers.Authorization = "Bearer xxxxxxxxxxxxxxxxxxxx"
body = [Request:[issueKey:issue.key, issueId:"this is passed through response"]]

response.success = { response, json ->
return json
}
response.failure = { resp, data ->
log.error " httprequest failed: $data"
return null
}
}

def flag = [type:'success',close:'auto']
def message = ""
if(response){
//here you can incorporate some data from the response into the message
message = "Succesfully posted to external api ($apiBase) with response: $response.issueId"
} else {
message = "There was an error posting data to external API. Please consult the Jira log"
flag.type = 'error'
flag.close = 'manual'
}

//use the next two line to display a flag to the user
flag.body = message
UserMessageUtil.flag(flag)

//use the following lines to create the fake issue history
//such fake issue history need to be given a "field name". That name doesn't have to exist or match an existing field
def historyFieldName = "POST RESULT" // <-change this to whatever makes sense to you
def currentUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def changeHolder = new DefaultIssueChangeHolder();
def changeItemBean = new ChangeItemBean(
ChangeItemBean.CUSTOM_FIELD, historyFieldName , "", "", "", message)
changeHolder.addChangeItem(changeItemBean);
def changeGroup = ChangeLogUtils.createChangeGroup(currentUser, issue, issue, changeHolder.getChangeItems(), false);

Hi Peter-Dave, 

Facing some error on the script, Could you check and fix them. Also IssueId has to get dynamically while post function option. Could you include the request in the code. 

Attached the error screen shots for reference.

BR,

Aditya.Dimage.png

 

image.png

If you look at line 17

body = [Request:[issueKey:issue.key]]

The issue object is provided by the script context. You can click on the question mark below the script editor to see all the variables provided by the scriptrunner script context. So in this case, we are setting the issueKey value in the body object to the key property of the issue object.

Most of these errors you see in the script are normal. The editor attempts to determine what type each variable is and if these types are appropriate for where they are used. But since groovy is not a strictly typed language, there are some things that the editor can't confirm. So it displays an error so that the coder can review and make sure it's appropriate.

Ultimately, you have to test the execution and review the logs to see what works.

The only error that I can't confirm if it will work or not is the one on line 32 since I haven't seen what your response json will look like to be sure if "$response.issueId" is valid. You can remove the .issueId part at least to start to get the full response.

Thanks Dave-Peter for detailed explanation. I run the code and got below error

2021-07-14 16:52:06,427 ERROR [runner.ScriptBindingsManager]:  httprequest failed: [response_map:[error_list:[[message:Unknown task: SchneiderDev/projects/Siddharth%20Shankar/JIRA-Access-TEST%20Task]]], http_status_code:404]

 BR,

Aditya.D

That looks like an error from your external endpoint.

http_status_coded:404 means "not found"

Are you sure this URI is correct?

SchneiderDev/projects/Siddharth%20Shankar/JIRA-Access-TEST%20Task

Thanks again Peter-Dave for the response.

I was able to run the code successful. But found one bug in the code. Post call is not passing the issuekey and issueid.  Could you please check?

 

I have code like : 

body = [Request:[issueKey:issue.key, issueId:"$response.issueId"]]

I don't know why you are attempting to use $response in the body... presumably that doesn't exist.

Are you trying to pass the id of the curret issue?

If so, it should look like this:

body = [Request:[issueKey:issue.key, issueId: issue.id as String]

What do you get when you output this?

log.info new groovy.json.JsonBuilder(body).toPrettyString()

 Can you give a full example of what you expect the body to look like?

Suggest an answer

Log in or Sign up to answer
TAGS
Community showcase
Published in Trello

🏊‍♀️ Atlympic Event: Trello

Hello Community!  Quick disclaimer: We are running a contest on Community (The Atlympics!) from July 23rd - August 8th of 2021. If you are interested in participating in this contest (prizes! ...

95 views 1 10
Read article

Community Events

Connect with like-minded Atlassian users at free events near you!

Find an event

Connect with like-minded Atlassian users at free events near you!

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you