![реализация автоматизации «как в Jira» в российском продукте](http://www.evateam.ru/wp-content/uploads/2023/03/Frame-238-1024x521.png)
Всем привет, меня зовут Алексей — я руководитель отдела интеграции EvaTeam. Это статья о том, как реализована настройка автоматизаций в EvaProject — российском аналоге Jira. В ней рассказывается о том, с чем пришлось столкнуться при переезде с Jira, и как мы реализовали функционал в нашей системе. Также прочитать эту статью вы можете в нашем блоге на Хабре.
Об автоматизации в Jira
Базовая автоматизация в Jira, прямо скажем, весьма скудная. Она подойдёт только небольшим и нетребовательным командам. По факту более менее полноценную автоматизацию можно получить только с использованием расширений и плагинов. Например, есть официальное расширение Jira Automation, которое позволяет добавлять свои правила. Но работа с ним тоже не очевидная и его болтает как матроса в лодке. Полноценно работает в премиум тарифе Cloud-версии. С недавних пор встроено в версию Data Centre. А для Server-тарифа устанавливается только как отдельное расширение с возможностью продлить его до февраля 2024 года.
Ещё есть плагины вроде ScriptRunner. Входит в топ самых популярных расширений в маркетплейсе и позволяет выстраивать процессы и автоматизации. Это действительно мощная вещь, которая может помочь организовать всё что происходит в компании. Но устанавливается отдельно и требует доплаты.
В целом у Jira богатая автоматизация за счет плагинов и расширений. Можно настроить всё что угодно: от смены исполнителя при изменении статуса по задаче, до включения кофемашины каждый день в 9 утра.
Поэтому возникают сложности у людей при переходе на российское ПО. Мало систем, которые позволят также гибко автоматизировать процессы, но и мы не из трусливых. Рассказываю о том, как работает этот функционал у нас в системе.
Автоматизация переходов
За основу работы автоматизации брались привычные настройки Jira, а также популярные плагины. В данный момент уже многое из этого реализовано в EvaProject, но ещё получаем много запросов, по специфичным настройкам, которые постоянно добавляем. Главное что сделано — заложены архитектурные возможности для дальнейшего развития в сторону замены Atlassian.
Для настройки логики бизнес-процессов используем классические 3 кита автоматизации:
- Условия перехода;
- Валидаторы;
- Действия.
Условия перехода
Условия перехода отрабатываются для визуального отображения в списке статусов. Они определяют именно видимость. Если условие для отображения перехода верное, то он будет отображаться в списке статусов. Например, можно настроить появление статуса «DONE» только тогда, когда в задаче оставили комментарий по ней.
![Условия перехода](http://www.evateam.ru/wp-content/uploads/2023/03/Frame-334-1024x505.png)
Отображение статуса при выполненном условии «Оставлен комментарий»
Валидатор
Это дополнительные условия для статусов. Если условие валидатора не выполняется, при переходе на определённый статус возникает ошибка. Валидатор фиксирует почему возникла ошибка и выводит информативное окно с причиной её возникновения.
![Появление окна с предупреждением при невыполненном условии](http://www.evateam.ru/wp-content/uploads/2023/03/Frame-445.png)
Появление окна с предупреждением при невыполненном условии
Используется для создания дополнительной логики при совершении переходов. Пример настройки сообщения для ошибки, получаемое пользователем при срабатывании определённых условий:
![Настройка валидатора](http://www.evateam.ru/wp-content/uploads/2023/03/Frame-098-1024x587.png)
Настройка валидатора
Примеры использования валидатора.
Например, нам нужно добавить условие, чтобы нельзя было изменить статус, если текущее время больше дедлайна, или изменять статус вне рабочего времени (к примеру, брать в работу).
Действия
Это именно то, что произойдёт в системе после смены статуса. Действие не накладывает дополнительных условий на отображение и смены статуса, а выполняется после перехода из одного статуса заявки в другой.
Помимо предустановленных опций для настроек переходов также доступен более гибкий инструмент bzPython, который является аналогом плагина ScriptRunner в Jira.
bzPyton
Используя bzPyton можно реализовать абсолютно любую автоматизацию.
![Пример добавления bzPython](http://www.evateam.ru/wp-content/uploads/2023/03/Frame-901-1024x581.png)
Пример добавления bzPython
bzPyton – внутренний бизнес-интерпретатор. Задача, в которой совершается определенный переход, передаётся в интерпретатор в переменной self, которая является объектом класса CmfTask и содержит всю информацию об этой задаче, то есть все поля и методы объекта CmfTask. Мы можем поменять статус, можем поменять будильник и любые другие поля, которые есть в модели CmfTask. Список доступных полей можно найти в официальной документации.
Для примера, сделаем чтобы ответственным для задачи стал пользователь, изменивший статус задачи. Добавляем новое действие для статуса, Вид Действия – bzPyton. В окно интерпретатора пишем:
self.responsible = g.current_user
В этом примере:
self.responsible – ответственный за текущую задачу;
g.current_user – специальная переменная, в которой содержится текущий пользователь, который совершает переход.
После окончания перехода, пользователь, совершивший этот переход, автоматически будет назначен ответственным по задаче.
Популярные шаблоны реализации автоматизации с помощью bzPyton можно посмотреть в официальной документации (https://docs.evateam.ru/docs/docs/DOC-000193#primery-bz-python)
Для переходов количество кода обычно невелико. Можно использовать более объемные скрипты в Триггерах или Cron.
И ещё один пример bzPython для валидатора. «Разрешить выполнять переход только тому пользователю, который является исполнителем по задаче»:
if self.responsible != g.current_user:
return False
Триггеры
Триггеры могут выполняться, когда в системе происходят какие-либо события. К примеру, кто-то перенес задачу в канбане на следующую стадию, наступил новый рабочий или любое другое событие. На него мы можем назначить триггер.
![Добавление события для триггера](http://www.evateam.ru/wp-content/uploads/2023/03/Frame-054-1024x527.png)
Добавление события для триггера
События для триггеров:
- Комментирование;
- Создание;
- Удаление;
- Сохранение;
- Обновление.
Любое это событие может быть использовано вместе с моделями:
- Задача (CmfTask);
- Документ (CmfDocument);
- Список (CmfList);
- Сделка (CmfDeal).
Для создания нового триггера необходимо перейти в настройки, выбрать режим администратора, нажать «Автоматизация триггеры».
В поле «Название» впишите нужное имя триггера и нажмите «Добавить».
Нажмите «Изменить», откроется окно с параметрами триггера.
![Настройка триггера](http://www.evateam.ru/wp-content/uploads/2023/03/Frame-150-1024x526.png)
Настройка триггера
Есть уже предустановленные фильтры. Это «Фильтр по логическому типу объекта», «Фильтр по виду деятельности», «Фильтр по схеме бизнес-процессов». Для более гибкой настройки фильтра есть возможность использовать интерпретатор bzPyton.
Подробное описание по настройкам содержится в официальной документации (https://docs.evateam.ru/docs/docs/DOC-000238#avtomatizacziya-triggery)
Попробуем работу триггеров.
Задача для триггера: Автоматизация по созданию дочерней задачи с типом «Подзадача».
Для этого выбираем такие настройки:
![настройки](http://www.evateam.ru/wp-content/uploads/2023/03/Frame-206.png)
Добавляем такой код:
task_code = self.name.value
relation_task = models.CmfTask.get(code=task_code, fields=['name', 'cf_custom_field_1'])
if relation_task:
# Меняем имя дочерней задачи
self.name = f'{task_code} - {relation_task.name}'
# Получаем кастомное поле из второй задачи
custom_1 = relation_task.cf_custom_field_1
# Меняем текст дочерней задачи
self.text = f'<p>Это текст первой строки. Кастом поле-{custom_1}</p>\n<p>Это текст второй строки</p>'
# Получаем нужный тип связи. В данном случае тип связи "Взаимная" - "Относится к"
relation_type = models.CmfRelationType.get(code='system.link')
# Создаем связь между второй задачей и новой созданной(дочерней)
new_rel = models.CmfRelationOption(out_link=self, in_link=relation_task, relation_type=relation_type)
new_rel.save()
А логика скрипта получается такой:
- Скрипт выполняется если в основной задаче нажать кнопку «Добавить дочернюю задачу» и прописать в названиеcode другой уже созданной задачи.
- По полю code будет найдена вторая задача. Из этой задачи будут получены поля name и cf_custom_field_1.
- Полученные поля из второй задачи будут прописаны в дочернюю.
- Между дочерней и второй задаче создается связь с типом system.link (Взаимная).
- В настройках триггера указано «Событие: Создание», «Фильтр по логическому типу объекта — Подзадача».
Cron
Автоматизировать работу системы можно не только по определённым действиям со стороны пользователей, но и по времени. Для этого есть специальный инструмент-планировщик. С помощью него, к примеру можно убирать выполненные задачи из списка задач, или настроить периодическую очистку архива.
Создать действие по времени можно также в настройках в режиме администратора. Для этого выбираем «Автоматизация Cron». Создаём новое правило и переходим к редактированию:
![Окно настройки Cron](http://www.evateam.ru/wp-content/uploads/2023/03/Frame-501-1024x520.png)
Окно настройки Cron
Выполняемые задачи для Cron не содержат переменную self. Вызываемые по расписанию объекты должны быть найдены в БД по определенному критерию. К примеру, по расписанию можно найти все задачи, у которых просрочен будильник, и изменить их статус. То есть с помощью Cron обычно производится автоматизация по большому списку задач, которые нужно раз в какой-то промежуток времени обработать.
Правила заполнения поля «Выражение Cron»
Время выполнения задается пятью колонками, разделёнными пробелами: минуты (0—59), часы (0—23), дни месяца(1—31), месяцы(1—12) и день недели(0—7). Значения могут быть в виде чисел, диапазонов или «». Примеры заполнения:
5 0 * * * – выполняется каждый день в 0 часов 5 минут;0-59 * * * * – выполняется ежеминутно;/5 * * * * – выполняется каждые пять минут;
5 4 * * sun – выполняется в 4:05 в воскресенье;
Рассмотрим пример. Нам нужно каждый день находить все задачи, у которых статус не менялся 7 дней, автоматически их закрывать и отправить уведомление владельцу задачи.
from datetime import timedelta
# Находим нужный workflow
wf = models.CmfWorkflow.get(code='WF-000005')
# Статус закрыто в нужном workflow
status_closed = models.CmfStatus.get(code='closed', workflow=wf)
seven_days_ago = g.now - timedelta(days=7)
# Находим задачи, у которых статус не менялся 7 дней
tasks = models.CmfTask.list(filter=['status_modified_at', '<=', seven_days_ago])
for task in tasks:
task.status = status_closed
task.save()
# Отправляем сообщение владельцу задачи
models.CmfNotify.place_notify(obj=task, person_id=task.cmf_owner.id.value,
msg=f'Заявка {task.code} отмечена как выполненная автоматически', text='Заголовок')
Помимо трёх вариантов автоматизации в EvaProject есть ещё Webhook и Git. Основные варианты автоматизации, благодаря bzPyton, имеют максимальную гибкость. Конкретные описания полей можно посмотреть в документации, либо обратиться в техподдержку.
Встроенный интерпретатор поддерживает подсветку синтаксиса, а также имеет подсказки по доступным командам. К примеру, если после self. нажать букву r, то мы увидим все возможные варианты. Все названия «говорящие», то есть по названию можно понять, что это за функция или переменная.
Конец
В следующей статье расскажу как мы помогали настраивать автоматизацию на примере одной крупной компании. Ну и это ещё минимальная часть от реализованного и планируемого функционала. Постоянно от клиентов получаем информацию о том как они «интересно» использовали Джиру и продолжаем добавлять фичи для автоматизаций.