Hi.
I'm looking for someone who is expert in custom JQL functions. I've implemented one cool custom JQL function and it's playing games with me . Same search with this JQL function is giving me different results. And it's completely random. I get 21 results and then 21, 21, 4, 21, 4, 21, 21, 21, 4, .... I've tried it debug it in Script Console but it works perfectly ther. Can anyone here help me to move along?
package com.onresolve.jira.groovy.jql
import com.atlassian.jira.JiraDataType
import com.atlassian.jira.JiraDataTypes
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.search.SearchProvider
import com.atlassian.jira.jql.operand.QueryLiteral
import com.atlassian.jira.jql.parser.JqlQueryParser
import com.atlassian.jira.jql.query.QueryCreationContext
import com.atlassian.jira.permission.ProjectPermissions
import com.atlassian.jira.security.PermissionManager
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.web.bean.PagerFilter
import com.atlassian.query.clause.TerminalClause
import com.atlassian.query.operand.FunctionOperand
import java.util.regex.Matcher
class ScopeOf extends AbstractScriptedJqlFunction implements JqlFunction {
PermissionManager permissionManager = ComponentAccessor.getPermissionManager()
List<Issue> finalListOfIssues
@Override
String getDescription() {
"Function finds all issues in scope of the issue"
}
@Override
List<Map> getArguments() {
[
[
"description": "Issue key or a subquery in \"\"",
optional: false
]
] as List<Map>
}
@Override
String getFunctionName() {
"scopeOf"
}
@Override
JiraDataType getDataType() {
JiraDataTypes.ISSUE
}
@Override
List<QueryLiteral> getValues(QueryCreationContext queryCreationContext, FunctionOperand operand, TerminalClause terminalClause) {
finalListOfIssues = []
ApplicationUser currentUser = queryCreationContext.getApplicationUser()
getListOfIssuesInScope(initialListOfIssues(operand.args[0], currentUser))
finalListOfIssues.unique().findAll {
queryCreationContext.securityOverriden || permissionManager.hasPermission(ProjectPermissions.BROWSE_PROJECTS, it as Issue, currentUser)
}.collect {
new QueryLiteral(operand, it.id)
}
}
List<Issue> initialListOfIssues(String operand, ApplicationUser currentUser) {
String pattern = /(?i)^"?[A-Z]+_?[A-Z\d]+-\d+"?$/
Matcher matcher = operand =~ pattern
String finalJQL
// argument is only one issue key
if(matcher) {
String issueKey = (matcher[0] as String).replace('"', '').replace("'", "")
finalJQL = "issue = ${issueKey}"
} else {
finalJQL = operand
}
return executeJqlQuery(finalJQL, currentUser)
}
List<Issue> executeJqlQuery(String queryString, ApplicationUser currentUser) {
def jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser)
def searchProvider = ComponentAccessor.getComponent(SearchProvider)
def query = jqlQueryParser.parseQuery(queryString)
def results = searchProvider.search(query, currentUser, PagerFilter.getUnlimitedFilter())
return results.getIssues()
}
List<Issue> getSubTasks(Issue issue) {
return ComponentAccessor.getSubTaskManager()
.getSubTaskObjects(issue) as List<Issue>
}
List<Issue> getIssuesUnderEpic(Issue epicIssue) {
return ComponentAccessor.getIssueLinkManager()
.getOutwardLinks(epicIssue.getId())
.findAll {link -> link.issueLinkType.name == "Epic-Story Link"}
.collect { link -> return link.destinationObject}
}
List<Issue> getSolvingIssues(Issue solvedIssue) {
return ComponentAccessor.getIssueLinkManager()
.getInwardLinks(solvedIssue.getId())
.findAll {link -> link.issueLinkType.name == "Solves"}
.collect { link -> return link.sourceObject}
}
def getListOfIssuesInScope(List<Issue> listOfIssues) {
List<Issue> listToContinueWith
for (Issue issue : listOfIssues) {
switch (issue.getIssueType().getName()) {
case ["Story", "Task", "Improvement"]:
finalListOfIssues += getSubTasks(it)
break
case ["Epic"]:
listToContinueWith = getIssuesUnderEpic(issue) - finalListOfIssues
finalListOfIssues += listToContinueWith
getListOfIssuesInScope(listToContinueWith)
break
case ["Idea", "Theme"]:
listToContinueWith = getSolvingIssues(issue) - finalListOfIssues
finalListOfIssues += listToContinueWith
getListOfIssuesInScope(listToContinueWith)
break
}
}
}
}
Hi @Martin Chalány Did your issue get resolved ?? Our team is facing a similar issue where some custom functions when used in JQL are giving inconsistent results.
Have you tried to use issueFunction IN linkedIssuesOfAllRecursive(<subQuery>) fuction? I believe is the same you are trying
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I know the JQL function, but the query for our full hierarchy (Theme -> Grand Idea -> Idea -> Epic -> Story -> Subtask) will be insane. We need our custom JQL function to it easier for anyone to get same result.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Get some debug logging in there to show you what the JQL is being turned into for the Lucene query part. Use one of the Lucene index tools to analyze your index to check it is not changing.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I've added a ton of logging into the script and the result is very interesting. The function getValues returns always the correct result. Inconsistency arises beyond this point. I don't understand why :'(
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Online forums and learning are now in one easy-to-use experience.
By continuing, you accept the updated Community Terms of Use and acknowledge the Privacy Policy. Your public name, photo, and achievements may be publicly visible and available in search engines.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.