ScriptRunner — это мощный плагин для Jira, который открывает практически безграничные возможности автоматизации. За годы работы я написал сотни скриптов: от простых автоматических действий до сложных интеграций. В этой статье разберу основы работы со ScriptRunner и покажу практические примеры, с которых можно начать.
Что такое ScriptRunner и зачем он нужен
ScriptRunner расширяет функциональность Jira через выполнение Groovy-скриптов. С его помощью можно автоматизировать практически любое действие в Jira, которое делается вручную через интерфейс или API.
Типичные задачи, которые решает ScriptRunner:
- Автоматизация workflow через кастомные пост-функции и валидаторы
- Массовые операции с задачами
- Интеграции с внешними системами
- Сложные вычисления в кастомных полях
- Обработка событий Jira
- Создание кастомных REST-эндпоинтов
Без ScriptRunner многие из этих задач либо невозможны, либо требуют разработки плагинов, что значительно сложнее и дороже.
Установка и первые шаги
ScriptRunner устанавливается как обычный плагин через UPM (Universal Plugin Manager). После установки в меню появится пункт "ScriptRunner".
Script Console — ваш главный инструмент
Script Console — это место, где вы будете писать и запускать скрипты. Находится в: Administration → ScriptRunner → Script Console.
В Script Console можно писать скрипты и запускать их сразу, видеть результаты выполнения. Это идеальная среда для экспериментов и отладки.
Основы Groovy для Jira
ScriptRunner использует язык Groovy, который похож на Java, но проще. Если вы знаете Java или другой похожий язык, вы быстро освоитесь. Если нет — Groovy достаточно простой для изучения.
Базовый синтаксис
Groovy не требует точек с запятой, автоматически определяет типы, имеет упрощённый синтаксис. Вот простой пример:
def number = 10
def text = "Hello"
def result = number * 2
log.warn("Result: ${result}")
def — это ключевое слово для определения переменной без указания типа.
log — это объект для логирования, доступный в ScriptRunner.
Работа с коллекциями
Groovy отлично работает с коллекциями (списки, карты). Вот примеры:
def list = [1, 2, 3, 4, 5]
def doubled = list.collect { it * 2 } // [2, 4, 6, 8, 10]
def filtered = list.findAll { it > 3 } // [4, 5]
def map = [name: "John", age: 30]
log.warn("Name: ${map.name}")
Это базовые конструкции, которые часто используются в скриптах для Jira.
Работа с задачами в ScriptRunner
Основной объект в Jira — это Issue (задача). Вот как с ним работать в ScriptRunner.
Получение задачи по ключу
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.IssueManager
def issueManager = ComponentAccessor.getIssueManager()
def issue = issueManager.getIssueObject("PROJ-123")
log.warn("Issue: ${issue.summary}")
log.warn("Status: ${issue.status.name}")
ComponentAccessor — это точка доступа к сервисам Jira.
Через него можно получить любые сервисы: IssueManager, UserManager, CustomFieldManager и т.д.
Чтение значений полей
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def assigneeField = customFieldManager.getCustomFieldObjectByName("Assignee")
def assignee = issue.getCustomFieldValue(assigneeField)
log.warn("Assignee: ${assignee?.displayName}")
Обратите внимание на ?. — это оператор безопасного доступа в Groovy.
Если assignee равен null, выражение вернёт null вместо ошибки.
Изменение задачи
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.user.ApplicationUser
def userManager = ComponentAccessor.getUserManager()
def currentUser = userManager.getUserByKey("admin")
def mutableIssue = issueManager.getIssueObject(issue.id) as MutableIssue
mutableIssue.setSummary("Новый заголовок")
mutableIssue.setAssignee(currentUser)
issueManager.updateIssue(currentUser, mutableIssue, com.atlassian.jira.event.type.EventDispatchOption.ISSUE_UPDATED, false)
Важно: для изменения задачи нужно получить MutableIssue и использовать updateIssue с указанием пользователя и параметров обновления.
Работа с кастомными полями
Кастомные поля — это частая задача в скриптах. Вот как с ними работать.
Получение кастомного поля
def customFieldManager = ComponentAccessor.getCustomFieldManager()
// По ID (customfield_10001)
def fieldById = customFieldManager.getCustomFieldObject(10001L)
// По имени
def fieldByName = customFieldManager.getCustomFieldObjectByName("My Custom Field")
// По ключу (если известен)
def fieldByKey = customFieldManager.getCustomFieldObjectByKey("com.atlassian.jira.ext.commitacceptance:github-pull-requests")
Чтение значения кастомного поля
def value = issue.getCustomFieldValue(fieldByName)
// Проверка типа поля
if (fieldByName.getCustomFieldType() instanceof com.atlassian.jira.issue.fields.config.FieldConfig) {
// Это поле типа Select List, User Picker и т.д.
log.warn("Value: ${value}")
} else if (fieldByName.getCustomFieldType() instanceof com.atlassian.jira.issue.customfields.CustomFieldType) {
// Другой тип поля
log.warn("Value: ${value}")
}
Установка значения кастомного поля
def mutableIssue = issueManager.getIssueObject(issue.id) as MutableIssue
// Для текстового поля
mutableIssue.setCustomFieldValue(fieldByName, "Новое значение")
// Для User Picker
def newUser = userManager.getUserByKey("john.doe")
mutableIssue.setCustomFieldValue(fieldByName, newUser)
// Для Select List (значение должно существовать в опциях)
mutableIssue.setCustomFieldValue(fieldByName, "Option Value")
issueManager.updateIssue(currentUser, mutableIssue, com.atlassian.jira.event.type.EventDispatchOption.ISSUE_UPDATED, false)
Поиск задач через JQL
ScriptRunner позволяет выполнять JQL-запросы программно:
import com.atlassian.jira.bc.issue.search.SearchService
import com.atlassian.jira.web.bean.PagerFilter
def searchService = ComponentAccessor.getComponent(SearchService)
def jqlQuery = "project = PROJ AND status = Open"
def user = userManager.getUserByKey("admin")
def query = searchService.parseQuery(user, jqlQuery)
def results = searchService.search(user, query.query, PagerFilter.getUnlimitedFilter())
results.results.each { issue ->
log.warn("Issue: ${issue.key} - ${issue.summary}")
}
Практический пример: автоматическое назначение
Вот пример скрипта, который автоматически назначает задачу на основе компонента:
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.user.ApplicationUser
def issueManager = ComponentAccessor.getIssueManager()
def userManager = ComponentAccessor.getUserManager()
def componentManager = ComponentAccessor.getComponentManager()
def issue = issueManager.getIssueObject("PROJ-123") as MutableIssue
def components = issue.components
// Маппинг компонентов на пользователей
def componentToUserMap = [
"Frontend": "frontend.dev",
"Backend": "backend.dev",
"Database": "db.admin"
]
def assignee = null
components.each { component ->
def userName = componentToUserMap[component.name]
if (userName) {
assignee = userManager.getUserByKey(userName)
}
}
if (assignee && issue.assignee != assignee) {
issue.setAssignee(assignee)
def currentUser = userManager.getUserByKey("admin")
issueManager.updateIssue(currentUser, issue, com.atlassian.jira.event.type.EventDispatchOption.ISSUE_UPDATED, false)
log.warn("Assigned ${issue.key} to ${assignee.displayName}")
}
Типичные ошибки новичков
Вот ошибки, которые часто допускают при начале работы со ScriptRunner:
Ошибка 1: Забыли импорты
Groovy требует явных импортов для многих классов. Если скрипт не компилируется, проверьте, все ли импорты добавлены.
Ошибка 2: Неправильное приведение типов
getIssueObject() возвращает Issue, но для изменения нужен MutableIssue.
Не забудьте приведение типа: as MutableIssue.
Ошибка 3: Забыли updateIssue
Изменение MutableIssue не сохраняется автоматически. Обязательно вызывайте updateIssue()
для сохранения изменений.
Ошибка 4: Null pointer exceptions
Всегда проверяйте на null или используйте безопасный доступ (?.).
В Jira много объектов могут быть null.
Отладка скриптов
Отладка в ScriptRunner — это логирование. Используйте log.warn() для вывода информации:
log.warn("Variable value: ${variable}")
log.warn("Issue key: ${issue.key}")
log.warn("Field value: ${fieldValue}")
Логи можно посмотреть в: Administration → System → Logging and profiling → View Logging.
Выводы
ScriptRunner открывает огромные возможности для автоматизации Jira. Начните с простых скриптов, экспериментируйте в Script Console, изучайте API Jira через документацию.
Основы, которые нужно освоить: работа с Issue, кастомными полями, поиск через JQL, изменение задач. После этого можно переходить к более сложным задачам: слушатели событий, кастомные поля, REST API.
Не бойтесь экспериментировать — Script Console позволяет безопасно тестировать скрипты. Начинайте с простого и постепенно усложняйте.
Если нужна помощь с написанием скриптов — свяжитесь со мной.