← Назад к статьям

Создание кастомных JQL функций через ScriptRunner

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 функций — свяжитесь со мной.