8 июня 2017

Блог

Как мы автоматизировали создание release notes

Release notes — это сопроводительный документ, который мы отправляем заказчику вместе с очередным релизом. Он должен быть точным, как инструкция по запуску космического корабля. Каждый относящийся к релизу багфикс, каждая закрытая user story и вся информация по user feedback должны быть четко отражены в отчете. Составлялся этот большой и важный документ вручную, копипастом из трекинговых программ. Вот тут-то и возникали сложности. 

В результате автоматизации мы избавились от ошибок и разнобоя в оформлении release notes. Дальше расскажем подробнее, как мы технически реализовали эту задачу и какие выгоды получили. 

Проблема 1. Ошибки.

При ручном составлении отчета иногда возникали ошибки. Некоторые наши проекты очень объемны и по технологическим причинам ведутся сразу в двух трекерах (например, часть проекта по созданию мобильного приложения ведется в Redmine, а по созданию веб-приложения — в TFS). Собирать по ним огромный отчет — долго и человеческий фактор мешал сделать все отчеты на 100% верифицированными.

Проблема 2. Разнобой в оформлении.

Кто-то из менеджеров проектов писал подробные комментарии к релизу, кто-то отправлял просто список работ. Красота оформления тоже страдала, поскольку release notes выглядел как обычное электронное письмо, хотя это одно из самых важных писем, которое приходит заказчику. Постепенно мы пришли к пониманию того, что создание отчетов по релизам нужно автоматизировать.

Что мы получили после автоматизации?

На нашем внутреннем портале появился веб-конструктор, который позволяет в несколько кликов собрать готовый отчет по релизу. Логинишься в приложение, выбираешь проект, релиз, нужные user story и таски, нажимаешь кнопочку — и остается только при необходимости дописать комментарии. По отзывам проджектов, эти простые действия приносят стойкое ощущение счастья.

Конструктор интегрирован с таск-трекерами и автоматически подтягивает в готовый release notes всю информацию по релизу. На выходе приложение генерирует красиво сверстанный e-mail отчет для заказчика. В нем вся информация разбита по категориям и каждый пункт снабжен ссылкой, ведущей на соответствующую страницу в трекере.

Вот так выглядит готовый сверстанный release notes:

image

В первый отправленный боевой отчет о выпущенном релизе вошло около 50 user story. В ворде такой документ занял бы 11 страниц. А на его создание в приложении ушло всего около 2 минут. Но главное не в экономии времени, а в том, что мы уверены в точности данных.

Управленческие бонусы
  1. Устранили ошибки в отчетах о релизах. Теперь заказчик оперативно получает 100-процентно выверенный release notes.
  2. Стандартизировали оформление отчета о релизах. Теперь наши release notes выглядят как красиво сверстанные в фирменном стиле html-файлы.
  3. Повысили качество ведения проектов в трекерах. Чтобы release notes сверстался одним нажатием волшебной кнопочки, менеджер проекта должен соблюдать в трекере идеальный порядок. Приятный бонус за это — автоматическое заполнение отчета. Конечно, автоматизацию мы затевали не ради экономии 1 часа рабочего времени. Главной целью было — обеспечить порядок и прозрачность в ведении проектов и красивый правильный отчет по релизу.
  4. Создаем шаблон для заказчика, в котором он может редактировать release notes и рассылать своим. Некоторым заказчикам наш html-файл с отчетом показался настолько удобным, что они попросили сделать аналогичный шаблон, в котором можно редактировать отчет для пересылки новым адресатам полного отчета или его частей с комментариями.
Автоматизация по шагам

Прежде чем делать свое решение для автоматизации, мы поискали готовые варианты. Теоретически для автоматизации составления release notes можно было использовать плагины к трекерам, в которых мы работаем (TFS, Redmine и JIRA). Но плагины у TFS и Redmine оказались неудобными. А для сборки единого отчета сразу из двух или трех трекеров вообще не нашлось готового решения. Поэтому нам пришлось сделать свое.

Шаг 1. Навели порядок в трекерах: ввели единые стандарты для менеджеров проектов, по которым они ведут проекты.

По технологическим причинам наши проекты ведутся в трех трекерах (TFS, JIRA, Redmine) и стандарты ведения проектов в них немного отличались. Для интеграции трекеров пришлось провести работу по внедрению единых стандартов для всех трекеров. Кроме того, понадобилось также причесать те блоки информации в трекерах, которые непосредственно экспортируются в release notes. Проект должен быть разбит по релизам, релизы поделены на задачи и у них проставлены статусы, все user story правильно описаны и закрыты, все задачи по фидбэку классифицированы, заведены все спринты. Кроме того, всем задачам и релизам должны быть даны понятные названия, ведь они потом войдут в отчет для заказчика

Шаг 2. Собрали Data WareHouse на основе данных из трекеров и MS Project Server

Мы построили представления над базами данных наших трекинговых систем (TFS, Redmine и JIRA), также подтянули некоторые данные из Microsoft Project Server (например, данные о заказчике). При этом нам пришлось решить некоторые проблемы с интеграцией данных из трекеров. Например, для каждого трекера пришлось найти индивидуальное решение проблемы с авторизацией для получения данных. Подробно об этом мы уже писали.

Для сбора данных мы использовали SQL Server Integration Services (SSIS).

image

Данные из трёх трекинговых систем (TFS, Redmine, JIRA) и Microsoft Project собираются в единое хранилище данных Data Warehouse.

Сначала загружаем данные из Microsoft Project.

image

Вот так выглядит скрипт загрузки проектов с информацией о заказчике и руководителе проекта.

SELECT proj.PROJ_NAME AS ProjectName
,proj.PROJ_UID as ProjectUID ,CT.Customer ,PCC.CostCenter ,PP.ProjectAccount ,pr_owner.RES_NAME AS ProjectOwner ,pr_owner.RES_UID as OwnerResourceNameUID ,CASE WHEN PPS.ProjectStatus IS NULL THEN 'Undefined' ELSE PPS.ProjectStatus END AS ProjectStatusFROM (SELECT PROJ_UID ,PROJ_NAME ,WRES_UID FROM pub.MSP_PROJECTS UNION SELECT 'E38038FA-F8CA-47D1-BFD4-6B45B8462972' AS Expr1 ,'Administrative' AS Expr2, NULL AS Expr3) AS proj LEFT OUTER JOIN pub.MSP_RESOURCES AS pr_owner ON pr_owner.RES_UID = proj.WRES_UID LEFT OUTER JOIN (SELECT pspPrjCFV.PROJ_UID ,psLV.LT_VALUE_TEXT AS Customer FROM ProjectWebApp_PSWA.pub.MSP_PROJ_CUSTOM_FIELD_VALUES AS pspPrjCFV INNER JOIN ProjectWebApp_PSWA.pub.MSP_CUSTOM_FIELDS AS pspCF ON pspCF.MD_PROP_UID = pspPrjCFV.MD_PROP_UID LEFT JOIN ProjectWebApp_PSWA.pub.MSP_LOOKUP_TABLE_VALUES AS psLV ON psLV.LT_STRUCT_UID = pspPrjCFV.CODE_VALUE WHERE (pspCF.MD_PROP_NAME = 'Customer') ) AS CT ON CT.PROJ_UID = proj.PROJ_UID LEFT OUTER JOIN (SELECT pspPrjCFV.PROJ_UID, psLV.LT_VALUE_TEXT AS CostCenter FROM pub.MSP_PROJ_CUSTOM_FIELD_VALUES AS pspPrjCFV INNER JOIN pub.MSP_CUSTOM_FIELDS AS pspCF ON pspPrjCFV.MD_PROP_UID = pspCF.MD_PROP_UID LEFT OUTER JOIN pub.MSP_LOOKUP_TABLE_VALUES AS psLV ON psLV.LT_STRUCT_UID = pspPrjCFV.CODE_VALUE WHERE (pspCF.MD_PROP_NAME = 'Cost_Center') ) AS PCC ON PCC.PROJ_UID = proj.PROJ_UID LEFT OUTER JOIN (SELECT pspPrjCFV.PROJ_UID, pspPrjCFV.TEXT_VALUE AS ProjectAccount FROM pub.MSP_PROJ_CUSTOM_FIELD_VALUES AS pspPrjCFV INNER JOIN pub.MSP_CUSTOM_FIELDS AS pspCF ON pspPrjCFV.MD_PROP_UID = pspCF.MD_PROP_UID WHERE (pspCF.MD_PROP_NAME = 'Project Account') ) AS PP ON PP.PROJ_UID = proj.PROJ_UID LEFT OUTER JOIN (SELECT pspPrjCFV.PROJ_UID, psLV.LT_VALUE_TEXT AS ProjectStatus FROM pub.MSP_PROJ_CUSTOM_FIELD_VALUES AS pspPrjCFV INNER JOIN pub.MSP_CUSTOM_FIELDS AS pspCF ON pspPrjCFV.MD_PROP_UID = pspCF.MD_PROP_UID LEFT OUTER JOIN pub.MSP_LOOKUP_TABLE_VALUES AS psLV ON psLV.LT_STRUCT_UID = pspPrjCFV.CODE_VALUE WHERE (pspCF.MD_PROP_NAME = 'Project Status') ) AS PPS ON PPS.PROJ_UID = proj.PROJ_UID

 

Далее, чтобы не заморачиваться с удалением старых данных, мы очищаем таблицы, связанные с задачами. И приступаем к сбору данных из трекинговых систем. Для каждой системы данные собираются по-своему. Как уже писалось в этой статье, для Redmine и TFS мы написали представления, которые возвращают нам все необходимые данные.

Так как доступа к базе JIRA у нас нет, то мы использовали JIRA REST APIi. Как вы сами понимаете, это самая медленная часть скрипта и куча возможностей для оптимизации. Но это уже отдельная история. После загрузки данных из трекеров нужно заполнить «пробелы» в таблицах проектов и сотрудников. Эти пробелы возникают в связи с тем, что не все проекты и сотрудники заведены в Microsoft Project в силу каких-то обстоятельств (либо не успели завести, либо исторически так сложилось). Отсутствующие данные сразу видны в отчете из OLAP куб, они помечены в отдельном столбце как Mismatch, и их можно сразу же обработать и навести порядок.

Далее осталось собрать всё воедино. Собираем вместе список задач.

image

И заполняем таблицу фактов (кто, куда и сколько потратил времени).

image

После чего мы запилили Job, который выполняет SSIS пакет раз в 3 минуты. И в итоге наш Data Warehouse готов. Далее с ним можно делать кучу полезных вещей. Например, собрать из него OLAP-куб для построения отчётов, или взять данные для Release Notes, или использовать для построения графика отпусков (да, да, про это тоже скоро расскажем).

Шаг 3. Сверстали красивый release notes нашей мечты.

Тут все просто: дизайнер и верстальщик сделали html-файл, в котором вся информация разбита по категориям, добавлены все необходимые ссылки.

Шаг 4. Сделали веб-приложение, которое на основе данных из Data Warehouse создает единый html-документ с отчетом для заказчика.

image

Шаг 5. Проект не останавливается.

Первые же письма вызвали восторженную реакцию заказчиков, и они попросили нас адаптировать шаблон под их бренд-буки и дать возможность самостоятельно редактировать наш release notes, сортируя информацию и добавляя комментарии для отправки новым адресатам.

image

А мы думаем, какие трудозатраты и бизнес-процессы еще оптимизировать...

Оригинал статьи опубликован на Habr