Перейти к содержанию

Пользовательские скрипты


Введение

Пользовательские скрипты - инструмент для создания самописных скриптов, выполняемых в 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