Custom Field from Forge App with JQL

Chris McKay June 15, 2021

I recently created my first Forge app. It is a simple text field that counts the number of Helpscout links added to a Jira issue.

My hope is to use this as a way of prioritizing feature requests and bug reports in Jira.

I have successfully

  • created the field
  • attached it to an issue
  • calculated the correct number of links
  • had the Scout Count field show in JQL

The last problem that I just can't seem to get is that the JQL cannot search or sort the values of the field. i.e. "Scout Count" > 0 returns nothing, even though there are issues with a correctly calculated number above zero.

I have also determined that the field is set to be searchable and sortable by fetching it.

I know that the fieldID is correct as the JQL search field suggests it 

Screenshot 2021-06-15 191120.png

I feel like it has to do with the idea that it's an unknown field type, but I have not been able to find how to adjust that. The manifest says it's a number and I've tried to apply the type and searcher key. Screenshot 2021-06-15 192835.png

This is my index.jsx

import api from '@forge/api';
import ForgeUI, { CustomField, CustomFieldEdit, render, Text, TextField, useProductContext, useState, Badge} from "@forge/ui";


//get the remote web links for the current issue
const fetchLinksForIssue = async (issueId) => {
const response = await api.asApp().requestJira(`/rest/api/3/issue/${issueId}/remotelink`);

let scouts = 0,
urlText = "";

const data = await response.json();

//count the HelpScout links
for(let i = 0; i < data.length; i++) {
urlText = data[i]["object"]["url"];

if(urlText.includes("helpscout")) {
scouts += 1;
}
}

return scouts;
};


function setFieldOptions (fieldId) {
var bodyData = `{
"searcherKey": "com.atlassian.jira.plugin.system.customfieldtypes:exactnumber",
"type": "com.atlassian.jira.plugin.system.customfieldtypes:textfield"
}`;

let response = api.asApp().requestJira('/rest/api/3/field/{fieldId}', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: bodyData
});

//console.log(bodyData);
console.log('Are my prints even working?' + response);
};


const View = () => {
const context = useProductContext();
const [fieldValue] = useState(async () => await fetchLinksForIssue(context.platformContext.issueKey));
setFieldOptions(10035);

return (
<CustomField>
<Text>
<Badge appearance = 'primary' text ={fieldValue} />
</Text>
</CustomField>
);
};


const Edit = () => {
const onSubmit = values => {
return values.text
};

return (
<CustomFieldEdit onSubmit={onSubmit}>
<TextField name="text" label="Say hello to:"></TextField>
</ CustomFieldEdit>
);
}


export const runView = render(
<View/>
);

export const runEdit = render(<Edit/>)

 This is my manifest.yml, excluding app:id

modules:
jira:customField:
- key: scoutcount
name: Scout Count
description: A count of HelpScout links for an issue.
type: number
validation:
expression: value == null || (value >= 0)
errorMessage: The value must consist only of numbers
readOnly: true
function: main
edit:
function: edit
function:
- key: main
handler: index.runView
- key: edit
handler: index.runEdit
app:
name: scoutCount
permissions:
scopes:
- manage:jira-configuration
- read:jira-work
- write:jira-work
- storage:app

 

2 answers

0 votes
Jeff Ryan {Appfire} August 12, 2021

@Chris McKay @Deon Petrus Meyer When I query using the /rest/api/2/search api I need to specify the custom field using the alternate form in my jql - like this:

{
"fields": ["id","key","summary","issuetype","customfield_10072"],
"jql": "cf[10072]>0"
}'

Chris McKay August 12, 2021

thanks for the reply @Jeff Ryan {Appfire}

My issue is that my app is producing a number and I am not able to search that value using JQL in the filters screen within Jira software. The field auto-populates, but when I search for values greater than 0, I get no results. 

I think the issue is that the value is not being calculated until an issue is opened, rather than it running on all issues and storing the value so it can then be searched.

Like Jeff Ryan {Appfire} likes this
Jeff Ryan {Appfire} August 12, 2021

Ah, got it. Yes you are exactly right there. When you add a custom field to a set of existing issues the value will not be calculated until the issue is displayed for the first time. We are experiencing this same issue with our custom field types.

Deon Petrus Meyer August 16, 2021

Hi @Chris McKay

I found an app that Atlassian built that demonstrates that the custom fields, to work with JQL, need to be calculated and stored ahead of time. The JQL search in Jira will look at the stored value, not the calculated one. Once you open the ticket, only then does the field get calculated (or whatever trigger you're using)

When building the custom field (that calculates a value) you need to 

1) update all instances of that field in Jira with an initial value

2) have a trigger that will keep the fields updated as needed.

 

For my field that I built, I opted out of the first option and only built the second one. 

That example can be found here: atlassian / forge-attachment-count-custom-field — Bitbucket

You'll notice the field key you need to set. This works as expected while the custom field is deployed to dev but as soon as I move the field to prod (and update the field key to reflect that of prod), the app starts to fail. I haven't found a solution for this yet. I haven't logged a ticket with Atlassian yet for this.

Jeff Ryan {Appfire} August 24, 2021

The backfilling of custom field values for existing issues is a serious problem in Forge given that the number of issues can be huge and the amount of time you have to calculate them during the create hook is limited. Atlassian themselves recommends against it. Unfortunately this means that searching and sorting on those values is not great if you have a lot of existing issues as you will simply have incomplete results.

Deon Petrus Meyer March 3, 2022

Not sure if this will help or if you found a workaround but we ended up doing this, for Read-only custom fields. Haven't found a better way yet. If there is, please let me know

  • Build the read-only forge custom field with 2 webtriggers
    • one for getting search parameters for the field(s) that apply in the calculation of the read-only value
      • it sends back jql to use in the search and fields to target
    • one to be used to trigger the custom field update rest endpoint (where you use the FIELD_KEY environment variable) and update multiple issues at once (provided in the payload)
  • Build a product trigger (we used Issue Create) that will update the underlying custom field for the issue created
  • Build an external app that we can search, collapse and mass-update the custom field values for multiple issues
  • When the app renders on a ticket, ensure it recalculates and stores the value first and then displays the stored value.

The sequence of events

  • create and deploy your forge app
  • generate the webtrigger urls
  • run custom external app providing the url for the search webtrigger
    • external app will get the search criteria from the custom field webtrigger results and execute JQL search 
    • collapse the search results so that tickets with the same value (for the target field in the search criteria) are grouped together
  • get the webtrigger url for the custom field update function
  • loop through each of the unique value(s) and post updates for all issues matching that have the same value
    • we added a pause after each execution to ensure we don't exceed invocation limits

Its a bit cumbersome but it does the trick. Afterwards, we redeploy the forge app and remove our webtriggers so that (should they be guessed by someone) it won't do any harm.

0 votes
Deon Petrus Meyer July 27, 2021

Hey @Chris McKay 

I'm having the same issue with custom fields I created. It seems that they don't execute when you do a JQL query with them in. 

I tried this even with a custom field that will always return data. 

Not sure if this is something to do with the Forge platform limits (see Platform quotas and limits (atlassian.com))

Looking forward to seeing what Atlassian says about this. 

Suggest an answer

Log in or Sign up to answer
DEPLOYMENT TYPE
CLOUD
PRODUCT PLAN
STANDARD
TAGS
AUG Leaders

Atlassian Community Events