Retrieving labels from multiple JIRA Subtasks via JIRA API - jira

I am creating a reporting dashboard with the intent of getting multiple tickets/issues for a project. As most of you probably know, a JIRA issue can have subtasks. These subtasks can have labels.
I want to retrive all labels for every subtask.
I already have the project API request implemented which returns the parent ticket ids along with the issue/ticket number of all subtasks. The problem is the data returned from this request does not include the labels for the subtasks themselves.
I can loop over each subtask number and make an additional API request for each one to get the labels, however this would result in a large number of requests.
Looking through JIRA's API I cannot find a better way of doing this. Google seems to return a lot of results about plugins and version differences with Cloud vs. Server but I have not found a better solution.
Their API makes reference to an expand option but I have yet to figure out a way to make that work for subtask labels (I might be missing something obvious).
If anyone has experience with a similar situation I would appreciate hearing any advice you could offer. Thanks!
What I have currently:
Project API Request:
https://ourcompanyhere.atlassian.net/rest/api/2/search
with an additional parameter added for the JQL string of:
project=PROJECTNAME AND fixversion=version
This returns all the tickets in the project with subtasks but not the subtask labels.
I can loop over the returned data from the above request and make an additional request for each:
https://ourcompanyhere.atlassian.net/rest/api/2/issue/ticketNumberHere
JSON Response
Here is the partial JSON response back (full response is huge and I've removed key information) however this is the complete information for a ticket, with a subtask which has labels. As you can see the labels section of the subtask is completely missing.
ErrorDetail=,
Mimetype=application/json,
Statuscode=200 OK,
Filecontent= {
"expand":"schema,names",
"startAt":0,
"maxResults":50,
"total":3,
"issues":[
{
"expand":"operations,versionedRepresentations,editmeta,changelog,renderedFields",
"id":"24209",
"self":"https://[instance].atlassian.net/rest/api/latest/issue/24209",
"key":"DEV-3089",
"fields":{
"issuetype":{
"self":"https://[instance].atlassian.net/rest/api/2/issuetype/10005",
"id":"10005",
"description":"A new feature of the product, which has yet to be developed.",
"iconUrl":"https://[instance].atlassian.net/secure/viewavatar?size=xsmall&avatarId=10311&avatarType=issuetype",
"name":"New Feature",
"subtask":false,
"avatarId":10311
},
"project":{
"self":"https://[instance].atlassian.net/rest/api/2/project/10000",
"id":"10000",
"key":"DEV",
"name":"Development Queue",
"avatarUrls":{
}
},
"customfield_11000":null,
"fixVersions":[
{
"self":"https://[instance].atlassian.net/rest/api/2/version/14600",
"id":"14600",
"description":"",
"name":"",
"archived":false,
"released":true,
"releaseDate":"2017-09-15"
}
],
"resolution":{
"self":"https://[instance].atlassian.net/rest/api/2/resolution/10000",
"id":"10000",
"description":"Work has been completed on this issue.",
"name":"Done"
},
"customfield_10500":"",
"customfield_10700":null,
"customfield_10900":null,
"resolutiondate":"2017-09-15T09:19:37.000-0400",
"workratio":-1,
"watches":{
"self":"https://[instance].atlassian.net/rest/api/2/issue/DEV-3089/watchers",
"watchCount":2,
"isWatching":true
},
"lastViewed":null,
"created":"2017-05-02T10:15:08.000-0400",
"customfield_10022":null,
"customfield_10100":null,
"priority":{
"self":"https://[instance].atlassian.net/rest/api/2/priority/3",
"iconUrl":"https://[instance].atlassian.net/images/icons/priorities/medium.svg",
"name":"Medium",
"id":"3"
},
"customfield_10300":null,
"labels":[
"[label1]",
"[label2]",
"[label3]",
"[label4]",
"[label5]",
"[label6]"
],
"customfield_10016":null,
"customfield_10017":null,
"versions":[
],
"issuelinks":[
],
"assignee":{
"self":"https://[instance].atlassian.net/rest/api/2/user?username=",
"name":"[name]",
"key":"[name]",
"accountId":"[account]",
"emailAddress":"[email]",
"avatarUrls":{
},
"displayName":"[name]",
"active":true,
"timeZone":"America/New_York"
},
"updated":"2017-09-15T09:19:36.000-0400",
"status":{
"self":"https://[instance].atlassian.net/rest/api/2/status/6",
"description":"The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.",
"iconUrl":"https://[instance].atlassian.net/images/icons/statuses/closed.png",
"name":"Closed",
"id":"6",
"statusCategory":{
"self":"https://[instance].atlassian.net/rest/api/2/statuscategory/3",
"id":3,
"key":"done",
"colorName":"green",
"name":"Done"
}
},
"components":[
],
"description":"[description]",
"customfield_10010":null,
"customfield_10011":null,
"customfield_11100":null,
"customfield_10012":null,
"customfield_10013":null,
"customfield_10015":"",
"customfield_10005":null,
"customfield_10006":null,
"customfield_10600":null,
"customfield_10007":null,
"customfield_10008":null,
"customfield_10800":null,
"customfield_10009":null,
"summary":"[summary]",
"creator":{
"self":"https://[instance].atlassian.net/rest/api/2/user?username=",
"name":"",
"key":"",
"accountId":"",
"emailAddress":"",
"avatarUrls":{
},
"displayName":"",
"active":true,
"timeZone":"America/New_York"
},
"subtasks":[
{
"id":"30213",
"key":"DEV-4118",
"self":"https://[instance].atlassian.net/rest/api/2/issue/30213",
"fields":{
"summary":"",
"status":{
"self":"https://[instance].atlassian.net/rest/api/2/status/6",
"description":"The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.",
"iconUrl":"https://[instance].atlassian.net/images/icons/statuses/closed.png",
"name":"Closed",
"id":"6",
"statusCategory":{
"self":"https://[instance].atlassian.net/rest/api/2/statuscategory/3",
"id":3,
"key":"done",
"colorName":"green",
"name":"Done"
}
},
"priority":{
"self":"https://[instance].atlassian.net/rest/api/2/priority/3",
"iconUrl":"https://[instance].atlassian.net/images/icons/priorities/medium.svg",
"name":"Medium",
"id":"3"
},
"issuetype":{
"self":"https://[instance].atlassian.net/rest/api/2/issuetype/10009",
"id":"10009",
"description":"",
"iconUrl":"https://[instance].atlassian.net/secure/viewavatar?size=xsmall&avatarId=10303&avatarType=issuetype",
"name":"Testing Issue",
"subtask":true,
"avatarId":10303
}
}
}
"reporter":{
"self":"https://[instance].atlassian.net/rest/api/2/user?username=",
"name":"",
"key":"",
"accountId":"",
"emailAddress":"",
"avatarUrls":{
},
"displayName":"",
"active":true,
"timeZone":"America/New_York"
},
"customfield_10000":"2017-09-01T12:35:54.706-0400",
"customfield_10001":null,
"customfield_10200":null,
"customfield_10400":null,
"customfield_10004":null,
"environment":null,
"duedate":null,
"votes":{
"self":"https://[instance].atlassian.net/rest/api/2/issue/DEV-3089/votes",
"votes":0,
"hasVoted":false
}
}
}
]
}

Inspect the response for the /search endpoint again. On a completely empty JIRA Cloud instance I created a Project, one Issue and added a Sub-task for it. Calling the /search endpoint returns a list with two Issues (so, the Issue itself and its Sub-task) and for both there's a field called labels with an array of all the Labels attached to it.
The following is an abbreviated response with all unrelated data removed.
{
"startAt": 0,
"maxResults": 50,
"total": 2,
"issues": [
{
"key": "TEST-1",
"fields": {
"labels": []
}
},
{
"key": "TEST-2",
"fields": {
"parent": {
"key": "TEST-1"
},
"labels": [
"VOILA"
]
}
}
]
}
EDIT
After looking at the response then yes, the array in subtasks is really simple and cannot be separately expanded. You need to do the search, then parse out all the subtasks that you're interested in and either do
a separate /issue/[key] request for each one
a /search for those specific keys

After doing some further research I found a better way to do this. I'm still not getting the subtask labels back but instead of looping over each subtask and sending a separate request for each, you can do one API call using JQL like this:
https://[instance].atlassian.net/rest/api/latest/search?jql=project=[project] AND KEY IN ([comma separated list of tickets])&fields=labels'
The
&fields=labels
part drastically reduces the amount of information returned. So now I can just do a total of two calls and get everything I need. :)
Wanted to post this in case anyone runs into a similar situation.

Related

Twilio Autopilot SMS not accepting media image type

I wrote a task a while back that would run a collect flow and collect an image using the model on the docs for doing so (https://www.twilio.com/docs/autopilot/actions/collect#questions). It ran flawlessly, and I tested it to make sure it ran as expected.
I made a new account using the company email to migrate my work over, and continue implementing the code, and eventually reached the portion where I needed to integrate that media collection. I used the same code, but it didn't work. The collect flow keeps on triggering the validate portion and telling me that it isn't an accepted type. I have tried it using the exact code from before as well as the exact image, but it still isn't working. The only thing I can think of is if the phone number was set up differently somehow. The message logs show the image as sent and looks fine and I can't find any differences other than that.
Is there anything that might be causing this? Here is the code for reference
{
"actions": [
{
"collect": {
"name": "image_collect",
"questions": [
{
"question": "Please upload an image",
"name": "image",
"type": "Twilio.MEDIA",
"validate": {
"on_failure": {
"messages": [
{
"say": "We do not accept this format. Please send another image."
}
]
},
"allowed_types": {
"list": [
"image/jpeg",
"image/gif",
"image/png",
"image/bmp",
"application/pdf"
]
}
}
}
],
"on_complete": {
"redirect": "https://4894-100-33-3-193.ngrok.io/image_processing"
}
}
}
]
}
Generally, media size causes this issue, just make sure the file size is within the limits.
For more info - https://www.twilio.com/docs/sms/accepted-mime-types

Can jenkins extended choice parameter be made dependent on another parameter's value?

I am using extended choice parameter with JSON parameter type in my declarative Jenkins pipeline. I have found it very good for providing custom UI for parameters and it returns a json based on user inputs.
I have a use case where what options are shown to user depends upon another parameter's value. I can achieve such functionality with active choice parameter but then I am stuck with radio buttons, checkbox, html input etc.
I found a suitable option here where I can make a property inside json dependent on another property:
{
"title": "An object",
"type": "object",
"properties": {
"fieldOne": {
"title": "I should be changed to 'foo'",
"type": "string",
"enum": ["foo","bar"],
"default": "bar"
},
"depender1": {
"title": "I depend on fieldOne to be 'foo'",
"type": "string",
"enum": ["lorem","ipsum"],
"options": {
"dependencies": {
"fieldOne": "foo"
}
}
},
"depender2": {
"title": "I depend on fieldOne to be 'bar'",
"type": "string",
"enum": ["dolor", "sit"],
"options": {
"dependencies": {
"fieldOne": "bar"
}
}
}
}
}
This works great when I try it here
But when I try the same on jenkins, it doesn't work. It shows all 3 textboxes. I saw the option of watching other params too but I couldn't find how to use it as an if else for my parameter.
This is a simple example, what I want to achieve requires UI of a dropdown-1 + Array(dropdown-2 + text field+text-field) where in array's text-field depend on value of dropdown-1, I cannot create the same UI in active choice.
Does any one know how options.dependencies could work in jenkins or same could be achieved using watch/other plugins?
if i got your question right, so you want to make it more smart way to select parameters.
So you can do it via groovy script.
Here is my example you can see on pic:
freestyle job config
Sorry, but i don't know how to better show freestyle job config.
So, logic is quite simple:
i'm collecting JSON on first parameter, and doing some parsing for it.
and then im using Environmets variable to show it's contents, depending on result from first part.
ps. i'm struggling right now with variable Hosts, as i don't know how to pass it in final steps without asking user for input.
But i believe you got the idea how you can do it.

How do I connect my database to API.AI?

How do I connect my database to API.AI
Making every sentence into INTENT and creating entities for each doesn't seem to be a good idea? So what is the best possible way to go about?
As far as I know it is not possible yet, but you can switch to row mode and past your entities inCVS or JSON format OR import a JSON/CSV file containing all your entities.
The file should look like below (JSON format):
[
{
"value": "val1",
"synonyms": [
"syn1",
"syn2"
]
},
{
"value": "val2",
"synonyms": [
"syn21",
"syn22"
]
},
]
So you can image of writing a small job that reads entities from you DB and make a JSON/CSV file according the wanted format.
Once the job done, this process may dramatically facilitate the creation of your entities on api.ai.
If you use a webhook for an intent, you can pass params to your endpoint where you can do all the queries to your db
I did a demo where I was querying news (cheating as I was getting it from the web, but I could plug a DB).
The was getting requests such as:
"What are the latest news about France"
latest and France would be params that I send through to the webhook endpoint.
You would get the following JSON sent your endpoint by API.AI
"result": {
"source": "agent",
"resolvedQuery": "latest news about France",
"action": "show.news",
"actionIncomplete": false,
"parameters": {
"adjective": "latest",
"subject": "France"
}
Then you can query all the news for France and order them by latest
In my understanding the idea is to create entities that are "placeholders" for the values you need to query.
Then you teach the AI with few examples by tagging in the request what did the person ask. Let say someone asks:
"what is the oldest news about France?"
The AI may not know what is oldest thus you tell it is is an adjective and from now on you can get oldest as a param

Time from creation to closed

I am trying to calculate the average time for all the jira cases that are created and until they are resolved.
How can this be done, for a specific project?
You dont say how you want to calculate this.
The simplest way is to add the Resolution Time Gadget to your dashboard. Here you can add a filter to specify which issues you want to consider.
This will give you a nice bar chart of the average resolution times of issues over a given period
If you want more control, you can write a script for it with the Jira REST API
If you create a jql for the issues you are interested in, you can call the REST api with a url like this:
https://jira.intern.sparebank1.no/rest/api/2/search?jql=assignee=e6462u
This will return a whole bunch of info, but you are most interested in the issues array elements, and specifically the fields "created" and "resolutiondate"
A snipped version of the JSON returned is:
{
"expand": "schema,names",
"startAt": 0,
"maxResults": 50,
"total": 1,
"issues": [
{
"expand": "operations,versionedRepresentations,editmeta,changelog,transitions,renderedFields",
"id": "104799",
"self": "https://jira.domain.com/rest/api/2/issue/104799",
"key": "HELLO-1",
"fields": {
...
"resolutiondate": "2015-06-25T09:12:27.000+0200",
"created": "2015-03-18T16:18:38.000+0100"
...
}
}
]
}
Now you can calculate the difference between the two for each issue element and find an average.
More info on Jira REST API: https://docs.atlassian.com/jira/REST/latest/
A blog I wrote on how to script stuff like this (and present in a graph in confluence ;) ): http://javamemento.blogspot.no/2016/05/jira-confluence-3.html

How to get the total number of issues of a JIRA Project?

Since JIRA API only allows to make a search request with a max result of 1000 issues, I need to know if there is a way to get the total number of issues a project so I can iterate through all thousands of issues.
IRestResponse responseIssues = client.Execute(new RestRequest("search?jql=project=" + "\"DATPROJECT\"" + "&maxResults=5000&fields=assignee,summary,timetracking,resolutiondate,resolution,worklog", Method.GET));
I am currently doing like the code above but I only get 1000 results and not 5000 that I need. I know that I can use the filter "startAt" to iterate over all results but I don't know how many issues exist.
Any ideas?
The search rest point returns total number of issues for a given JQL search. Example result from documentation
{
"expand": "names,schema",
"startAt": 0,
"maxResults": 50,
"total": 1,
"issues": [
{
"expand": "",
"id": "10001",
"self": "http://www.example.com/jira/rest/api/2/issue/10001",
"key": "HSP-1"
}
]
}
This "total":1 value is the one you're looking for.
Hey from rest Api I don't find any rest where you can get all issue.but if you want all issue you can get it from java side. if you need total number of issues use
long getIssueCountForProject (Long projectId)
and if you want all issues and want to iterate it use
Collection<Long> getIssueIdsForProject (Long projectId)
please refer atlassian documentation for all this method.
Thank you.
You can use maxResults=0 to get only descriptive data omitting the actual results.
For example, if we want to know the amount of open issues for the currently logged in user:
rest/api/2/search?jql=project=SP+AND+statusCategory!=3+AND+assignee+in+(currentUser())&maxResults=0
The result:
{
"startAt": "0",
"maxResults": "0",
"total": "68",
"issues": [
]
}
The "total" field here is just what we need.

Resources