Как мы интегрировали Jira с Хантфлоу и автоматизировали процессы по подбору персонала

Внедрение тасктрекеров и их последующая интеграция с другими системами – распространенная практика во многих компаниях. При этом интеграции, по сути, создают настоящий сборник нестандартных задач для разработчика. Множество интересных кейсов в разрезе интеграции систем есть и в компании OCS. О наших доработках на базе Jira, а конкретно – об интеграции платформы с CRM для рекрутмента Хантфлоу (Huntflow) и автоматизации процессов подбора персонала, - рассказывает Виталий Тиллер, руководитель отдела разработки Atlassian. Этот кейс будет полезен тем, кто занимается «приземлением» Хантфлоу на Jira, заведует автоматизацией процессов в HR и просто хочет узнать больше о возможностях интеграций Jira.

Цели и задачи


Шаг 1. Базовая автоматизация
Первое, что мы сделали в Jira – создали шаблон, по которому можно легко заполнить параметры необходимой вакансии: новая ли это должность, замена ли ушедшему сотруднику, условия, требуемый стаж. Форма подачи заявки была стандартизирована с учетом всех требований HR. Здесь мы столкнулись с первыми нюансами.

Дело в том, что при заполнении шаблона инициатор задачи должен целиком заполнить иерархию подразделений (от департамента до отдела и группы). В нашем случае иерархия состоит из 5 ступеней, и далеко не всегда последний по иерархии отдел находится на 5 ступени. Для синхронизации иерархического справочника подразделений используем плагин Insight. В нем мы создали схему, куда ежедневно синхронизируем из внешнего источника данные о структуре компании. Затем через Scriptrunner Behaviours при создании новой задачи реализована проверка заполнения до последнего доступного департамента.

Подачу заявок мы стандартизировали – но жизнь HR глобально это не облегчило. Какое-то время им пришлось работать с двумя системами одновременно: заявка создавалась инициатором в Jira, где он мог отслеживать ее выполнение, и вручную дублировалась в Хантфлоу.

Из плюсов: руководители HR получили возможность видеть проект целиком и создавать отчеты, инициатор задачи также отслеживал весь прогресс по заявке. Но это была лишь вершина того «айсберга», с которым нам предстояло работать.

Шаг 2. Передача статусов
И в Jira, и в Хантфлоу задача «Кандидат» совершает переход по определенным статусам: в работе, на согласовании оффера, на проверке и так далее. Чтобы HR не пришлось делать двойную работу и переводить статусы и там, и там, все автоматизировано. На каждый переход по статусам в Jira мы добавили пост-функцию с кастомным скриптом, которая проверяет, существует ли релевантный статус в Хантфлоу и, если таковой есть, отправляет туда HTTP запрос на изменение статуса кандидата. Конечно, совпадают не все точки, но реферные, такие как «отказ», «оффер согласован», «оффер принят» сопоставимы и синхронизированы. Например, если мы в Jira переводим кандидата в статус «Вышел на работу» - в этот же статус он автоматически попадает и в Хантфлоу.

Это все сделано в виде простой матрицы: когда в Jira выполняется переход на новый статус и такой этап присутствует в Хантфлоу, статус автоматически обновляется. Если совпадения статусов нет, скрипт ничего не отправляет.

Шаг 3. Интеграции на этапе поиска кандидата
Итак, заявка подана по шаблону. Как только рекрутер берет ее в работу, в дело вступают интеграции. Автоматически вызывается определенный скрипт, существующий как постфункция в воркфлоу для вакансии. Он собирает все необходимые данные из задачи в Jira и отправляет их в Хантфлоу, создавая сущность «вакансия». Если на вакансии есть квота (допустим, 5 человек на позицию Q&A), они точно так же передаются в Хантфлоу как обычное цифровое поле.

В ответе Хантфлоу мы получаем ID созданной вакансии – он фиксируется в задаче и используется для дальнейшей интеграции. Для обратной связи мы запросили у ребят из Хантфлоу кастомное поле – JiraIssue – его мы заполняем при создании вакансии. Таким образом эти две сущности оказываются связаны друг с другом, что позволяет далее осуществлять обмен данными в обе стороны.

На этом этапе работа в Jira на время останавливается. Рекрутеры продолжают взаимодействовать только с Хантфлоу до момента, пока не находят финального кандидата или кандидатов.

И здесь мы столкнулись с крайне интересной задачей.

Схема взаимодействия Jira и Huntflow

Шаг 4. Укрощение строптивых вебхуков
В Хантфлоу реализован механизм вебхуков. Они отправляются по всем событиям и разным объектам: могут уходить на изменения сущностей и «вакансия», и «кандидат». При этом со стороны Хантфлоу нет возможности отфильтровать события, по которым уходят вебхуки - а нас интересует лишь одно конкретное, когда кандидат перешел на стадию «согласование оффера».

Это можно было бы решить с помощью кастомного REST Endpoint через тот же ScriptRunner, но исторически сложилось так, что Jira у нас расположена во внутреннем контуре. Соответственно, мы не можем предоставить наружу API: ни стандартную Rest API, ни написанную самостоятельно.

Поэтому для решения данной проблемы нам пришлось написать промежуточный сервис на Java Spring Boot. Этот сервис является своеобразным proxy-сервером между закрытым контуром Jira и интернетом. Он и сам закрыт сетевым экраном безопасности, снаружи доступны лишь некоторые endpoints, в которые можно попадать только с определенных IP-адресов. С помощью сервиса мы решаем и вопрос безопасности, и трансляции входящего вебхука в Jira Rest API, то есть просто компонуем полученные в хуке данные в стандартный Jira Rest API.

Важно понимать, что мы делали этот сервис в авральном режиме. Сами прописали преобразования входящих вебхуков в Jira Rest API, прикрутили Spring Security. Сейчас, уже имея некоторый опыт, мы понимаем, что среди готовых библиотек доступных в Maven Repository есть Jira Rest Java Client (jira-rest-java-client-core), которая уже является готовым решением и позволяет осуществлять трансляцию входящих кастомных вещей в Jira Rest API намного проще. И хотя со временем наш кастомный сервис вырос от взаимодействия только с Хантфлоу до работы с другими внешними системами, мы планируем изменить его и настроить работу уже через эту библиотеку.

Шаг 5. Уникальные ссылки
Итак, сервис успешно фильтрует входящие вебхуки до момента, пока не появляется уведомление о том, что в Хантфлоу кандидат перешел на стадию «согласование оффера». В этот момент у основной задачи в Jira, появляется подзадача «Кандидат». В исходном хуке от Хантфлоу содержится ограниченная информация по кандидату и в момент создания задачи отдельный скрипт отправляет запрос всех данных по кандидату – он собирает все недостающие данные и загружает в задачу как вложения резюме и фото кандидата, если они доступны.

В Jira из полей задачи другой скрипт из различных данных задачи формирует уникальный UUID. В задаче есть поле – ссылка на анкету безопасности, веб-интерфейс которой находится за пределами Jira, сфомированный UUID же добавляется в ссылку как обычный параметр GET запроса. Рекрутер передает ее соискателю любым возможным способом. UUID штука уникальная и тем самым позволяет однозначно связать анкету с конкретной задаче, при этом не «светить» наружу issueKey, например. Когда открывается ссылка, вебсайт обращается к нашему Jira Proxy, о котором я говорил выше, а он уже с помощью простого JQL ищет, существует-ли задача с таким UUID. Если задача найдена не будет, сервис об этом сообщит, и веб-форма вернет пользователю ошибку – ссылка неверная!

Если же все хорошо и задача найдена, пользователю предлагается заполнить анкету и после нажатия кнопки «отправить» через Jira Proxy все данные попадают в нужную задачу в Jira. В CMS появляется отметка о том, что данные были отправлены, и при попытке повторно пройти по ссылке отображается предупреждение – «Анкета уже заполнена».

Что нам дает UUID?
1. Безопасность
2. Конфиденциальность персональной информации

Шаг 6. Одобрение кандидата
Анкета кандидата автоматически передается в службу безопасности. Мы снимаем эту задачу с плеч рекрутера, уменьшаем количество ошибок при ручной передаче информации. У задачи «Кандидат» появляется соответствующий статус «На проверке СБ». Если при проверке возникают замечания – проверяющему достаточно выбрать соответствующий признак при закрытии задачи и все заинтересованные лица тут же получат уведомление в почту.

Далее оффер согласовывают ответственные лица: рекрутер, инициатор задачи и отдел кадров. Для автоматизации этой задачи в Jira мы использовали бесплатный плагин Approvals. К сожалению, в плагине не получается в роли согласующего указать Assignee, пришлось прикрутить невидимое кастомное поле «рекрутер», которое дублирует поле «assignee» в Jira и менять его при любой смене Assignee. Это делается через Jira Automation.

Шаг 7. Подготовка к выходу на работу и адаптация кандидата
Адаптация кандидата начинается с момента, когда оффер принят. Ответственные начинают готовить рабочее место, учетные записи, технику. С технической же стороны происходит следующее. Когда кандидат принимает оффер, заполняется несколько полей: плановая дата выхода, должность (мы синхронизируемся с ЗУП) и локация нашего нового коллеги. Все данные собираются в POST-запрос, который улетает через API в ЗУП (за что спасибо коллегам из 1С), а там уже автоматически формируется приказ и все необходимые документы.
Одновременно с этим формируется вторая UUID-ссылка на форму, где кандидат коротко рассказывает о себе и добавляет фото. Этот рассказ собирается в HTML-файл и добавляется к задаче Jira, связанной с этим кандидатом. Механизм работы этой фичи такой же как у анкеты, описанной выше. Несложное правило в Automation напоминает ответственному рекрутеру о приближающейся дате выхода сотрудника.

В день выхода нового сотрудника, всем его кураторам отправляется уведомление с ФИО новичка, названием должности и фото – это уведомление формируется отдельным groovy-скриптом, все данные, в том числе и фото берутся из задачи.

Руководители больших департаментов и директора компании имеют возможность отключить уведомления, чтобы не утонуть в потоке писем. Для этого достаточно поставить галочку - скрипт, собирая адресатов для письма, залезает в Insight справочник и проверяет признак «исключить из рассылки». Да, мы также синхронизируем в Insight и списки наших сотрудников, в том числе для реализации подобных функций (а еще там есть галочка «включить уведомления в Rocket.Chat, но об этом в другой раз)

Помните поле «Квота»? В момент перехода подзадачи типа «Кандидат» в статус «Вышел на работу» небольшой скрипт проверяет, сколько таких «Вышедших» есть по задаче на подбор. Если число подзадач в нужном статусе равно квоте – автоматом закрывается и задача на подбор, и ее «брат-близнец» в Хантфлоу (да, туда опять отправляется HTTP запрос)
В момент перевода подзадачи «Кандидат» в статус «Оффер принят» рекрутер имеет возможность установить признак «Требуется адаптация» и указать ответственного за этот процесс. Адаптация – это процесс, в котором собрано порядка 20 регламентных задач с разным сроком начала и конца и разными исполнителями. Чтобы в Jira эти задачи возникали автоматически, в Insight мы создали отдельную схему с описанием таких задач. Для задачи выбирается один из нескольких возможных исполнителей – рекрутер, сам новичок, или ответственный за адаптацию новичка сотрудник. Кроме того у каждой задачи есть точка старта и завершения плюс поля для модификации этих дат, например, мы можем указать, что задача «Знакомство с коллегами» должна начаться в срок «Дата фактического выхода на работу» + 2 дня, а завершится не позднее срок «Дата фактического выхода на работу» + 5 дней, исполнитель по задаче – ответственный за адаптацию новичка сотрудник.

Задачи на адаптацию создаются в два этапа – при приеме оффера и при выходе на работу, когда новичок уже присутствует в Jira как пользователь и ему могут быть назначены задачи.
Созданием этих задач занимается очередной Groovy-скрипт – он получает список задач из схемы Инсайта, и в цикле создает по ним, как по шаблону задачи в отдельном проекте, заполняя данные из шаблона реальными – вместо «Исполнителя» устанавливает текущего Assignee из задачи, по которой создается адаптация и так далее.

Итого

Итоги
Все эти изменения и доработки заняли не один месяц. И это не конец: система продолжает расти, развиваться, а заказчики приходят с новыми просьбами и идеями. Возможно, не все было реализовано идеально – но уже на этом этапе мы настроили основные интеграции и автоматизировали процессы, чтобы облегчить жизнь коллегам из HR и выстроить воркфлоу.




Для обеспечения качественной работы сайта, идентификации его посетителей, а также сбора статистики посещений наш сайт использует файлы Cookies (куки-файлы), сервисы веб-аналитики и онлайн-маркетинга. Вы можете согласиться или отказаться от использования файлов Cookies.

Вы можете запретить сохранение файлов Cookie в настройках Вашего браузера.

Подробнее о cookie файлах можно узнать здесь