ScriptRunner · Data Center

ScriptRunner Data Center: читаем поле по ID, когда имена совпадают

Диагностика одного кастомного поля через HAPI: сверяем ID, контекст и тип значения, проверяем соседнее одноимённое поле и не раскрываем содержимое в журнале.

Применимость: Data Center. Названия пунктов и доступность функций зависят от версии, плана и типа проекта. Проверяйте изменения на тестовом окружении. Описанные рабочие процедуры — предлагаемый подход, а не гарантии поставщика.

Почему имя поля не всегда достаточно

В интерфейсе задача показывает заполненное поле, а скрипт получает null или неожиданное значение. Одна из причин — несколько кастомных полей с одинаковым именем. Прежде чем менять данные или переписывать условие, нужно установить, какое именно поле читает код. В учебном пилоте проверим одну задачу, один подтверждённый ID и результат без вывода самого значения.

Инструкция относится к ScriptRunner for Jira Data Center и HAPI в Script Console. HAPI появился в ScriptRunner 7.11.0, однако это не обещание совместимости каждого актуального примера со всеми старыми сборками. Зафиксируйте версии Jira и ScriptRunner, проверьте документацию установленной ветки и доступность используемых методов. Обновление приложения или сервера ради этого пилота не требуется.

В ScriptRunner Cloud другой API и контекст выполнения. Нельзя переносить этот серверный пример целиком в облачную консоль или считать ID одинаковым между сайтами. Числовые идентификаторы ниже условные: их нужно заменить значениями из своей среды. Код не выполнялся на реальном Jira Data Center при подготовке статьи.

Подготовьте ограниченный набор для проверки

Выберите учебный проект PILOT и нейтральную задачу, например PILOT-1. Понадобятся разрешённый административный доступ к Script Console и возможность проверить конфигурацию поля. Консоль умеет выполнять гораздо более широкие действия, чем чтение, поэтому доступ к ней не следует выдавать обычным пользователям только для диагностики.

Согласуйте владельца поля, ожидаемое назначение и тип данных. Для простого пилота удобно обычное текстовое поле, а не поле стороннего приложения с собственным вычислением. Если одноимённые поля уже существуют, сначала опишите их; не создавайте новые глобальные дубли ради эксперимента. Для отдельной тестовой модели заранее ограничьте область применения и используйте нейтральные значения.

Запишите ключ задачи, тип задачи, ID выбранного поля, его имя и исходное состояние. Сохраните прежний текст проверяемого скрипта, если он будет временно заменяться. В этом пилоте достаточно вставить отдельный читающий фрагмент в консоль: редактировать рабочий Listener, валидатор или вычисляемое поле не нужно.

Сверьте ID и контекст до запуска Groovy

В административном разделе Custom fields найдите нужное поле и откройте его конфигурацию. Сопоставьте имя, тип и идентификатор в адресе настройки, например fieldId=customfield_12345. Для HAPI числовая часть этого идентификатора — 12345; в примере используется 12345L. Имя может помогать человеку, но именно подтверждённый ID выбирает объект поля в данной среде.

Если есть другое поле с таким же именем, запишите его ID отдельно и отметьте назначение. Не выбирайте первый результат списка по внешнему виду. Не подменяйте custom field ID идентификатором контекста, экрана, опции списка или конфигурации поля: это разные объекты, хотя все они могут отображаться как числа.

Проверьте контекст: нужное поле должно применяться к проекту и типу контрольной задачи. Контекст не равен схеме конфигурации полей. Если поле не видно в интерфейсе, отдельно проверьте экран и скрытие поля. Не расширяйте контекст на все проекты как универсальное исправление: сначала подтвердите, что выбран правильный объект.

Прочитайте поле по подтверждённому ID

В Script Console вставьте фрагмент ниже. Замените ключ задачи и числовой ID, сохранив ограничение проекта. Классы HAPI, включая Issues, автоматически доступны в скриптах, компилируемых ScriptRunner. Если в существующем коде уже импортирован другой класс Issues, устраните конфликт по документации автоматических импортов, а не добавляйте случайные пакеты из чужого примера.

Фрагмент получает одну задачу и читает одно значение. Возвращается диагностическая карта: ключ, выбранный ID, признак null и имя Java-типа. Сам текст поля не печатается. Здесь нет update, сохранения задачи, перехода workflow или массового поиска. Тем не менее запускать его нужно только в согласованной среде и от разрешённой учётной записи.

final String issueKey = 'PILOT-1'
final Long fieldId = 12345L

def issue = Issues.getByKey(issueKey)
if (issue.projectObject.key != 'PILOT') {
    throw new IllegalArgumentException('Only the PILOT project is allowed')
}

def value = issue.getCustomFieldValue(fieldId)
return [
    issueKey: issue.key,
    customFieldId: fieldId,
    valueIsNull: value == null,
    valueType: value == null ? null : value.getClass().getSimpleName()
]

Проверьте положительный и отрицательный примеры

Для положительного случая выберите тестовую задачу, где подтверждённое текстовое поле содержит нейтральное значение. Ожидается valueIsNull=false; тип результата должен соответствовать выбранному типу поля. Проверьте, что в карте указан именно согласованный ID. Сама карта не доказывает правильность содержимого: сравнение с интерфейсом выполняет пользователь с разрешённым доступом.

Для отрицательного случая используйте ту же задачу с пустым выбранным полем либо другую согласованную задачу с таким исходным состоянием. При известном пустом текстовом поле проверьте фактический результат своей версии; не считайте любое пустое отображение доказательством null. Если возвращена пустая строка, valueIsNull останется false. Для списков пустая коллекция также отличается от null.

Если есть два одноимённых поля, подготовьте случай, где одно заполнено, а второе пусто, и повторите чтение с их подтверждёнными ID по отдельности. Разница должна объясняться конкретными полями и исходными данными. Не угадывайте, какое из них выбрал бы вызов по имени, и не используйте такой вызов как контрольный эталон.

  • Ключ задачи и ID в результате совпадают с согласованной записью.
  • Заполненное поле отличается от контролируемого пустого состояния.
  • Одноимённое соседнее поле проверяется отдельным ID.
  • Вне PILOT защитная проверка не допускает чтения значения этим фрагментом.

Разберите кэширование и различия типов

HAPI кэширует поля объекта issue при его получении. Если более длинный скрипт сначала прочитал поле, затем изменил его, повторный getter того же объекта может показать прежнее значение. Adaptavist описывает refresh() для получения обновлённого состояния. В нашем читающем пилоте нет записи; для повторной ручной проверки заново запустите фрагмент, чтобы получить задачу заново.

Не добавляйте refresh в цикл без понимания причины. Он не исправляет неверный ID, неподходящий контекст или ошибочное ожидание типа. Если поле возвращает Option, коллекцию, пользователя или объект приложения, обработка как обычной строки может быть неверной. Сначала установите контракт поля и проверьте его справку, затем проектируйте сравнение и только после этого изменение.

При null не начинайте сразу с переиндексации или записи в базу. Сверьте задачу, поле, контекст и текущую конфигурацию. Ошибка чтения и отсутствие значения — разные результаты: сохраните класс ошибки и нейтральное описание шага, не публикуя полный объект задачи или содержимое закрытых полей.

Подготовьте изменение рабочего скрипта отдельно

Если диагностика подтвердила выбор неверного одноимённого поля, изменение рабочего кода должно явно ссылаться на нужный идентификатор. До выпуска найдите другие места, использующие прежнее имя, и проверьте их назначение. Не заменяйте все совпадения имени по репозиторию автоматически: разные проекты могли намеренно работать с разными полями.

ID устойчив к переименованию конкретного поля, но не является универсальным переносимым ключом между экземплярами. При переносе скрипта на другой стенд или в Cloud потребуется отдельное соответствие полей. Храните такую конфигурацию с пояснением среды и назначения, а не в виде ничем не объяснённого числа посреди большого скрипта.

Чтение под административной записью не подтверждает доступ обычного пользователя или корректность будущего изменения. Если логика станет частью Listener или workflow, повторно проверьте контекст исполнения, разрешения, ограничения нагрузки и откат. Не добавляйте обход прав ради успешной проверки одного getter.

Откат и передача результатов владельцу поля

Сам читающий фрагмент не изменяет задачу, поэтому откатывать её после такого запуска не требуется. Если для пилота вручную менялись нейтральные значения, восстановите их по исходной записи и согласуйте результат с владельцем. Не удаляйте рабочие поля, контексты или задачи ради очистки эксперимента.

Если проверялся отдельный вариант скрипта, верните прежний текст и сохраните диагностический вариант отдельно с указанием среды. Рабочие функции не должны переключаться автоматически из-за результата этого пилота. Составьте короткую запись: версии Jira и ScriptRunner, ключ, ID и тип поля, контекст, наблюдение null или типа и оставшиеся вопросы.

Методы и ограничения в материале сверены с официальными источниками; Groovy-код не компилировался и не запускался в реальной Jira. Приёмка в вашей среде завершена после положительного примера, контролируемого пустого состояния, проверки соседнего одноимённого поля и подтверждения отсутствия незапланированных изменений.

Официальная документация

Применить это к вашей системе

Обсудим контекст, ограничения и безопасный порядок изменений.

Обсудить задачу