Пользовательские скрипты
Введение
Пользовательские скрипты - инструмент для создания самописных скриптов, выполняемых в GitFlic и взаимодействующий с его сущностями. Скрипты выполняются на JavaScript стандарта ECMAScript версии 2022-го года. Благодаря данной функции, команды разработки самостоятельно могут создавать интеграции со сторонними инструментами и сервисами, настраивать автоматизацию внутри GitFlic по своим сценариям.
Ещё одна ценность инструмента - открытый исходный код интеграций. Чтобы интегрировать свой развёрнутый GitFlic, достаточно скопировать из репозитория с интеграциями нужные файлы и добавить их через интерфейс. Это не требует сложных конфигураций, развёртывания или взаимодействия с REST-API GitFlic.
Использование
Взаимодействие с сущностями происходит через сервисы - объекты с набором методов, позволяющих создавать новые, изменять или получать уже имеющиеся сущности в GitFlic. Для того чтобы лучше понимать, что принимают и возвращают сервисы, даётся определение нескольких классов:
Объект страницы содержит в себе следующие данные:
class Page<T> {...}
Название | Тип данных | Описание |
---|---|---|
page |
number | Номер текущей страницы |
size |
number | Число элементов на текущей страницы |
pageSize |
number | Максимальный число элементов на страницы |
totalPages |
number | Всего страниц |
totalElements |
number | Всего элементов |
elements |
T[] - массив сущностей | Список элементов |
Сущности и методы
Подробно ознакомиться с сущностями и их методами можно по ссылкам ниже:
Метод | Вызов метода |
---|---|
Создание лейбла | labelService.create |
Изменение лейбл | labelService.edit |
Получение списка всех лейблов | labelService.getAll |
Получение списка лейблов по UUID | labelService.findAllByIds |
Метод | Вызов метода |
---|---|
Создание проблемы | issueService.create |
Изменение проблемы | issueService.edit |
Получение списка всех проблем | issueService.getAll |
Получение списка всех проблем с указанным статусом | issueService.getAllWithStatus |
Получение проблемы по локальному номеру | issueService.findByLocalId |
Получение проблемы по UUID | issueService.findById |
Метод | Вызов метода |
---|---|
Создание комментария к проблеме | issueNoteService.create |
Изменение комментария к проблеме | issueNoteService.edit |
Получение списка всех комментариев к проблеме | issueNoteService.findAll |
Получение комментария к проблеме по UUID | issueNoteService.findById |
Получение количества комментариев в проблеме | issueNoteService.countAll |
Метод | Вызов метода |
---|---|
Создание запроса на слияние | mergeRequestService.create |
Изменение запроса на слияние | mergeRequestService.edit |
Изменение статуса запроса на слияние | mergeRequestService.editStatus |
Получение списка запросов на слияние по исходному проекту | mergeRequestService.findAllBySourceProject |
Получение списка запросов на слияние по целевому проекту | mergeRequestService.findAllByTargetProject |
Поиск запроса на слияние по UUID | mergeRequestService.findById |
Поиск запроса на слияние по локальному номеру | mergeRequestService.findByLocalId |
Проверка существования запроса на слияние | mergeRequestService.exists |
Проверка возможности слить запрос на слияние | mergeRequestService.canMerge |
Дискуссия к запросу на слияние
Метод | Вызов метода |
---|---|
Создание дискуссии к запросу на слияние | noteService.create |
Изменение дискуссии к запросу на слияние | noteService.edit |
Создание ответа в дискуссии к запросу на слияние | noteService.reply |
Закрытие дискуссии к запросу на слияние | noteService.resolve |
Открытие дискуссии к запросу на слияние | noteService.unresolve |
Получение списка всех дискуссий к запросу на слияние | noteService.findAllInMergeRequest |
Получение дискуссии к запросу на слияние по UUID | noteService.findById |
Метод | Вызов метода |
---|---|
Создание конвейера | pipelineService.create |
Создание пустого конвейера | pipelineService.createBlank |
Получение списка всех конвейеров | pipelineService.findAllByProject |
Получение списка конвейеров по ветке или тегу | pipelineService.findByProjectIdAndRef |
Получение конвейера по локальному номеру | pipelineService.findByLocalId |
Получение конвейера по UUID | pipelineService.findById |
Получение списка конвейеров в запросе на слияние | pipelineService.findByMergeRequestId |
Перезапуск конвейера | pipelineService.restart |
Отмена конвейера | pipelineService.cancelPipeline |
Изменение статуса конвейера | pipelineService.changeStatus |
Обновление времени начала выполнения конвейера | pipelineService.setStartTime |
Обновление времени окончания выполнения конвейера | pipelineService.setFinishTime |
Изменение времени выполнения конвейера | pipelineService.setExecutionTime |
Создание стадии | pipelineService.createStage |
Изменение статуса стадии | pipelineService.changeStageStatus |
http запросы
На текущий момент поддерживаются следующие методы для работы с http запросами:
http.get(url: string, config?: RequestConfig) => HttpResponse
http.post(url: string, body: any, config?: RequestConfig) => HttpResponse
где RequestConfig и HttpResponse - следующие классы (написаны на typescript):
interface HttpRequestConfig {
url?: string;
method?: string;
baseUrl?: string;
headers?: { [key: string]: string[] };
params?: { [key: string]: string[] };
data?: any;
auth?: {username: string, password: string}
}
interface HttpResponse {
body: any;
isSuccessful: boolean;
code: number;
message: string;
headers: { [key: string]: string[] };
}
Пример использования:
Пример GET-запроса к REST-API Gitflic
const url = '${baseurl}/user/me'
req = http.get(url,{ headers: { "Authorization": `token ${gitflicApiToken}` }});
console.log(JSON.stringify(req))
req.code
Пример POST-запроса, не требующий передачи body
const url = ${exampleUrl}
req = http.get(url,{},{headers: { "Authorization": `token ${token}` }});
console.log(JSON.stringify(req))
req.code
Права
При создании скрипта сохраняется его автор. Набор прав, которыми обладает автор скрипта будет влиять на то, какой функционал будет доступен в рамках выполнения этого скрипта.
Например, пользователь, которому не доступно создание конвейеров, но доступна работа со скриптами (такого поведения возможно добиться при использовании пользовательской роли), создает скрипт, создающий конвейер. Этот скрипт не будет создавать конвейер, даже если его будет запускать пользователь с доступом к созданию конвейеров.
Переменные
В разделе Переменные находится интерфейс добавления и настройки переменных скриптов. В поле Название укажите название переменной, в поле Значение укажите её значение. Редактирование и удаление существующих переменных происходит в этом же разделе. Для использования переменных в скрипте необходимо добавить их в настройках каждого скрипта по отдельности.
Способы запуска скриптов
Запустить пользовательский скрипт можно несколькими способами:
Запуск из веб-интерфейса
Любой скрипт можно запустить прямо из интерфейса. Для этого необходимо перейти в сам скрипт и нажать на соответсвующую кнопку в разделе с управлением скриптов. Существует два типа запуска:
- Полноценный запуск - выполнение скрипта с изменениями в базе данных. Данный вид запуска подходит для использования отлаженных скриптов.
- Тестовый запуск - выполнение переменных без изменений в базе данных. Данный вид запуска подходит для настройки и проверки работоспособности скриптов.
REST-API
При помощи данного REST-API запроса можно выполнить скрипт. С инструкцией по получению токена доступа для работы с публичным API можно ознакомиться здесь.
POST {baseUrl}/rest-api/project/{userAlias}/{projectAlias}/script/{uuid}
Переменная пути запроса | Тип | Описание |
---|---|---|
baseUrl |
String | URL, на который будет отправлен запрос |
ownerAlias |
String | Псевдоним владельца проекта |
projectAlias |
String | Псевдоним проекта |
scriptUuid |
String | UUID скрипта на выполнение |
Переменная
{baseUrl}
зависит от конфигурации GitFlic. Например, она может принимать следующее значение:localhost:8080
Запрос возвращает следующую информацию:
Параметр | Тип | Описание |
---|---|---|
executionUuid |
String | UUID результата выполнения |
scriptUuid |
String | UUID пользовательского скрипта |
triggerType |
String | Тип триггера. Всегда возвращает REQUEST |
triggerName |
String | Название триггера. Всегда возвращает rest-api |
triggeringUserUuid |
String | UUID пользователя, запустившего скрипт |
executionStartTimestamp |
Long | Время начала выполнения скрипта |
executionEndTimestamp |
Long | Время окончания выполнения скрипта |
queueAppendTimestamp |
Long | Время добавления в очередь на выполнение |
result |
String | Результат выполнения. Возможные значения: SUCCESS - успешное выполнение, RUNTIME_ERROR - ошибка во время выполнения, TIME_EXCEEDED - превышение время выполнения и UNKNOWN_ERROR - неизвестная ошибка |
returnedValue |
String | Возвращенное значение |
Триггеры
Для автоматического выполнения скрипта после наступления определенного события необходимо воспользоваться триггерами. К одному скрипту можно добавить до 10 разных триггеров.
Существует несколько групп триггеров. Каждое событие в группе возвращает дополнительные переменные окружения:
Конвейеры {#pipelineEvents}
- Новый конвейер
NEW_PIPELINE
- Удачно завершившийся конвейер
SUCCESS_PIPELINE
- Неудачно завершившийся конвейер
FAIL_PIPELINE
- Удаление конвейера
DELETE_PIPELINE
Название переменной | Тип | Описание |
---|---|---|
projectId |
string | UUID проекта, к которому относится конвейер |
userId |
string | UUID пользователя, который вызвал событие |
authorUsername |
string | Псевдоним пользователя, который вызвал событие |
status |
string | Статус конвейера на момент наступления события |
localId |
number | Локальный номер конвейера |
ref |
string | git-ссылка на тег или ветку, на котором был запущен конвейер |
isTag |
boolean | Конвейер создан на тег true или на ветку false |
commitAfter |
string | Хеш коммита, на котором был запущен конвейер |
Запросы на слияние {#mergeRequestEvents}
- Создание запроса на слияние
NEW_MERGE_REQUEST
- Обновление запроса на слияние
UPDATE_MERGE_REQUEST
- Слияние запроса на слияние
MERGE
- Закрытие запроса на слияние
CLOSE_MERGE_REQUEST
- Отмена запроса на слияние
CANCELED_MERGE_REQUEST
Название переменной | Тип | Описание |
---|---|---|
sourceProjectId |
string | UUID исходного проекта запроса на слияние |
targetProjectId |
string | UUID целевого проекта запроса на слияние |
localId |
number | Локальный номер запроса на слияние |
authorId |
string | UUID автора запроса на слияние |
authorUsername |
string | Псевдоним автора запроса на слияние |
assignedUsers |
string[] | Список ответственных в запросе на слияние |
targetBranch |
string | Целевая ветка запроса на слияние |
sourceBranch |
string | Исходная ветка запроса на слияние |
title |
string | Название запроса на слияние |
description |
string | Описание запроса на слияние |
status |
string | Статус запроса на слияние на момент наступления события. Возможные значения: OPENED , MERGED , FAILED , CONFLICT , CANCELED , CLOSED , REVERTED |
Дискуссии к запросу на слияние {#mergeRequestNoteEvents}
- Создание комментария в дискуссии к запросу на слияние
NEW_MERGE_REQUEST_NOTE
Название переменной | Тип | Описание |
---|---|---|
projectId |
string | UUID проекта, в котором создана дискуссия к запросу на слияние |
userId |
string | UUID автора дискуссии |
message |
string | Содержание дискуссии |
authorUsername |
string | Псевдоним автора дискуссии |
noteId |
string | UUID созданной дискуссии |
status |
string | Статус дискуссии. Возможные значения: RESOLDEV и UNRESOLDEV |
Проблемы {#issueEvents}
- Создание проблемы
NEW_ISSUE
- Обновление проблемы
UPDATE_ISSUE
- Закрытие проблемы
CLOSE_ISSUE
Если для срабатывания скрипта одновременно выбраны триггеры на Обновление проблемы и Закрытие проблемы, то при закрытии проблемы, скрипт сработает два раза.
Название переменной | Тип | Описание |
---|---|---|
projectId |
string | UUID проекта, к которому относится проблема |
localId |
number | Локальный номер проблемы |
authorId |
string | UUID автора проблемы |
authorUsername |
string | Псевдоним автора проблемы |
title |
string | Заголовок проблемы |
assignedUsers |
string[] | Список ответственных в проблеме |
status |
string | Статус проблемы на момент наступления события. Возможные значения: OPEN , IN_PROGRESS , CLOSED , COMPLETED |
Комментарии к проблеме {#issueNoteEvents}
- Создание комментария к проблеме
NEW_ISSUE_NOTE
Название переменной | Тип | Описание |
---|---|---|
projectId |
string | UUID проекта, к которому относится проблема |
issueLocalId |
number | Локальный номер проблемы |
message |
string | Содержание комментария |
authorId |
string | UUID автора комментария |
authorUsername |
string | Псевдоним автора проблемы |
Элементы git {#gitEvents}
- Создание ветки
NEW_BRANCH
- Обновление ветки
UPDATE_BRANCH
- Удаление ветки
DELETE_BRANCH
- Создание тега
NEW_TAG
- Удаление тега
DELETE_TAG
Название переменной | Тип | Описание |
---|---|---|
projectId |
string | UUID проекта, в котором произошло событие |
userId |
string | UUID пользователя, который совершил действие |
ref |
string | git-ссылка на тег или ветку |
commitBefore |
string | последний коммит в ветке до пуша |
commitAfter |
string | последний коммит в ветке после пуша |
Ограничения
Определены ограничения на ресурсы среды выполнения, а также дополнительные ограничения со стороны сервисов.
Все настройки управляются через файл конфигурации application.properties
Описание настройки | Название в файле конфигурации | Значение по умолчанию |
---|---|---|
Максимальное время выполнения скрипта в миллисекундах | scripts.limits.max-execution-time-millis |
1000 |
Максимальное количество вызовов сервисов в рамках одного скрипта | scripts.limits.max-calls-per-context |
10 |
Максимальное число выражений (условия, циклы и т.п.) в рамках одного скрипта | scripts.limits.max-statements |
1000 |
Пример работы ограничения на число выражений:
Если
scripts.limits.max-statements = 1000
,то скрипт завершится с ошибкой при обращении к телу любого цикла 1001 раз.
Примеры
Подсчет количества комментариев в Проблеме {#gitEvents}
var issueNoteCount = issueNoteService.countAll(issueId);
issueNoteCount
Необходимо дополнительно объявить переменную
issueId
Создание запроса на слияние после пуша новой ветки {#gitEvents}
var newMergeRequest = mergeRequestService.create({
sourceProjectId: projectId,
targetProjectId: projectId,
targetBranch: "master",
sourceBranch: ref,
title: "Новый функционал",
description: "Добавление новой функциональности в проект",
removeSourceBranch: true,
workInProgress: false,
squashCommit: true
});
console.log("Созданный запрос на слияние:");
console.log(JSON.stringify(newMergeRequest, null, 2));
var canMergeMergeRequest = mergeRequestService.canMerge(newMergeRequest.id);
if (canMergeMergeRequest) {
console.log('\n', "Запрос на слияние можно слить");
}
else {
console.log('\n', "Запрос на слияние нельзя слить");
}
var newNote = noteService.create({
mergeRequestId: newMergeRequest.id,
message: "Этот запрос создан автоматически, с использованием пользовательского скрипта"
});
Необходимо дополнительно объявить переменную
projectId