JQL (Jira Query Language) — мощный инструмент поиска задач, но иногда стандартных функций недостаточно для сложных запросов. ScriptRunner позволяет создавать кастомные JQL функции, которые расширяют возможности поиска. В этой статье разберу, как создавать полезные JQL функции для решения практических задач.
Зачем нужны кастомные JQL функции
Кастомные JQL функции полезны для:
- Поиска задач по сложным критериям, которые невозможно выразить стандартным JQL
- Агрегации данных из связанных задач
- Вычисления значений на основе нескольких полей
- Интеграции с внешними данными в запросах
Функции делают JQL более выразительным и позволяют создавать сложные запросы, которые было бы невозможно написать стандартными средствами.
Создание простой JQL функции
Создайте функцию через: Administration → ScriptRunner → JQL Functions → Add function.
Пример функции, которая находит задачи, обновлённые за последние N дней:
import com.atlassian.jira.issue.Issue
import java.util.concurrent.TimeUnit
def days = args.first() as Integer ?: 7
def cutoffDate = new Date(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(days))
issues.findAll { Issue issue ->
issue.updated > cutoffDate
}
Использование: issueFunction in updatedInLastDays("14")
Функция для поиска задач с открытыми блокерами
Находит задачи, которые блокируются незакрытыми задачами:
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.link.IssueLinkManager
def issueLinkManager = ComponentAccessor.getIssueLinkManager()
issues.findAll { Issue issue ->
def links = issueLinkManager.getInwardLinks(issue.id)
def blockers = links.findAll { link ->
link.issueLinkType.name == "Blocks" && link.getSourceObject().resolution == null
}
!blockers.empty
}
Использование: issueFunction in hasOpenBlockers()
Функция для агрегации подзадач
Находит задачи, у которых все подзадачи закрыты:
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.IssueManager
def issueManager = ComponentAccessor.getIssueManager()
issues.findAll { Issue issue ->
def subTasks = issueManager.getSubTaskObjects(issue.id)
if (subTasks.empty) {
return false
}
subTasks.every { it.resolution != null }
}
Использование: issueFunction in allSubTasksClosed()
Функция с параметрами
Функция, которая находит задачи, назначенные на членов определённой группы:
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.user.util.UserManager
def groupName = args.first()?.toString() ?: return []
def userManager = ComponentAccessor.getUserManager()
def groupManager = ComponentAccessor.getGroupManager()
def group = groupManager.getGroup(groupName)
if (!group) {
return []
}
def users = groupManager.getUsersInGroup(group)
issues.findAll { Issue issue ->
issue.assignee && users.contains(issue.assignee)
}
Использование: issueFunction in assignedToGroup("developers")
Вычисления в функциях
Функция для поиска задач с просроченным дедлайном:
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def dueDateField = customFieldManager.getCustomFieldObjectByName("Due Date")
def now = new Date()
issues.findAll { Issue issue ->
def dueDate = issue.getCustomFieldValue(dueDateField) as Date
dueDate && dueDate.before(now) && issue.resolution == null
}
Использование: issueFunction in overdueTasks()
Производительность JQL функций
JQL функции выполняются для каждой задачи в результате запроса. Поэтому важно, чтобы они были быстрыми:
- Кэшируйте результаты — для дорогих операций используйте кэш
- Ограничивайте область поиска — используйте функции вместе с ограничивающими условиями
- Избегайте сложных операций — не делайте множественные запросы к БД или внешним API
Типичные ошибки
Вот ошибки, которые часто допускают при создании JQL функций:
Ошибка 1: Медленные функции
Функция выполняется для каждой задачи. Если она медленная, весь запрос будет медленным. Оптимизируйте функции и используйте кэширование.
Ошибка 2: Неправильная обработка параметров
Всегда проверяйте параметры на null и корректность. Неправильная обработка может привести к ошибкам выполнения.
Выводы
Кастомные JQL функции расширяют возможности поиска в Jira, позволяя создавать сложные запросы, которые невозможно выразить стандартным JQL.
Создавайте функции для типичных задач поиска, оптимизируйте их для производительности, тестируйте на разных наборах данных.
Если нужна помощь с созданием JQL функций — свяжитесь со мной.