Заметки

Мои мысли о жизни, работе и разных интересных штуках вокруг меня.

Показано: 0 · Страница

Новый UI в блоге
17 января 2026 ·
Блог
Готово

На новогодних праздниках внезапно закусился и переписал UI блога. Хотел всего-то прикрутить поиск по заметкам: их уже довольно много и время от времени нужно что-то быстро выудить из кучи написанного (например, ссылку коллеге скинуть).

Блог живёт на Github Pages, так что выбор решений небогат: либо слать запрос в гугл, либо делать свой статический индекс и отдавать в браузер пользователя (пусть сам в нём роется). Я пошёл по второму пути: быстрее, управляемее и можно самому покодить. При первом поиске файл индекса, правда, нужно скачать, но что такое 200 Кб в современном интернете? Смешно.

Ну а там как-то, знаете ли, пошло-поехало... Сначала не удавалось прикрутить к полю поиска Tachyons — разозлился и переделал всё на Tailwind (всё равно хотел попробовать, а случая всё никак не представлялось). Пока писал код для поиска — подумал, что логично сразу вкрутить в него теги, чтобы два раза не вставать. Очнулся с облаком тегов над заметками и сообразил, что тогда уж надо и к проектнику что-то в этом духе прикрутить, только там не теги нужны, а стеки...

В общем, получилось как в том меме из «Страха и отвращения в Лас-Вегасе». Сложно было остановиться. Осталось теперь заставить себя писать в новый проектник: работы всегда дофига, и работа интересная, но если не записывать всё — кофе, всё тонет в кофе.

Управление бэкапами
6 декабря 2025 ·
Работа
Готово

В конце года выкатили для нашего внутреннего инструмента (я уже вскользь писал о нём) большой апдейт, дающий коллегам адекватный доступ к бэкапам пользовательских приложений. Бэкапы в SaaS-компании нужны всем и всегда — для разработки, для тестирования, для расследования проблем, да много для чего. Без адекватного учёта процесс превращается в зоопарк, когда три человека в один момент времени создают три запроса на практически одинаковые копии одной и той же базы. Задача, конечно, решается, но ресурсов прожрано в три раза больше, чем хотелось бы.

У нас уже было решение на базе UI Битрикса, но в силу, э-э, особенностей развития этого продукта оно приносило больше боли, чем пользы. Поэтому мы переосмыслили процесс и всё переписали. На фронте — 1C, на бэке — PostgREST, PostgreSQL, PowerShell и много чего ещё. Логика довольно сложная, но у пользователя — простой и дружелюбный UI, через который можно заказать бэкап буквально в два нажатия.

Выбрать можно один из трёх видов бэкапов:

  • облачный (копия реального приложения, развёрнутая в облаке и доступная, в том числе, через браузер);
  • файловый бэкап (обычный .dt-файл, который можно скачать и развернуть на локальной машине);
  • бэкап конфигурации и расширений (.cf + .cfe).

Кроме того, новое решение отслеживает попытки заказать бэкап приложения, если он уже делается прямо сейчас. А ещё — не даёт пользователям бэкапить одно и то же приложение чаще, чем раз в час.

Ну и продолжаем хохмить в интерфейсе, конечно.

But Still!

Coffee First!

Протоптанные дорожки
29 ноября 2025 ·
Работа
Оптимизация

Ладно, загадка Жана Фреско. У вас есть таблица, скажем, на 50 тысяч строк. Как прочитать из неё полмиллиарда?

Раз плюнуть, Nested Loops + Clustered Index Seek:

Полмиллиарда

От Clustered Index Seek тут одно название, конечно. Фактически оператор при каждом исполнении пробегает по всей таблице (всему кластерному индексу) и сверяет каждую запись с Predicates. И так — 10 730 раз для 51 391 записей. В итоге 551 425 430 строк прочитали, 13 343 вернули.

Ох

Короче, идеальный пример плохого плана запроса в вакууме, хоть сейчас тащи в палату мер и весов. Nested Loops, если кто позабыл, работает примерно так:

For Each Table1Row In Table1 Do
    For Each Table2Row In Table2 Do
        ...

Это ОК для мелких таблиц, но СУБД может его применить и для таблиц поболбше — например, если ей не хватает времени на построение плана.

Это и произошло в нашем случае. Прыгнем повыше, на уровень платформы: тут у нас динамический список с запросом по таблице документа, к которой разработчики прицепили с десяток виртуальных таблиц регистров накопления.

Некоторые регистры и сами по себе были здоровенными, а виртуальные таблицы дополнительно поддали жару (каждая превращается в 2+ вложенных запроса). СУБД честно пыталась придумать эффективный алгоритм, но в какой-то момент решала, что хреновый план запроса всё же лучше, чем вообще никакого.

В итоге пользователь что? Пытался поискать документ по номеру и клиентское приложение просто-напросто зависало.

Короче, по поводу виртуальных таблиц в динамических списках. В английском есть выражение «desire path», «протоптанная дорожка». Часто прицепить виртуальную таблицу к основной — и в самом деле самый простой, быстрый и привычный способ решить задачу. Но он не эффективен.

Есть, например, обработчик ПриПолученииДанныхНаСервере(). Он дольше в реализации, но позволяет хорошо затюнить виртуальную таблицу и избежать сценария выше. На каждую прокрутку списка получится больше запросов, но они будут быстрее и эффективнее, чем один, но гигантский.

Дневник питания в Obsidian Bases
23 ноября 2025 ·
Готово
Obsidian

Переписал с помощью Obsidian Bases свой прошлогодний плагин, считающий калории, белки, жиры и углеводы в пище. Получилось сильно более гибкая и настраиваемая штука, чем в виде плагина — не нужно ничего переписывать, собирать и релизить, если вдруг решил посчитать клетчатку в еде или просто подвигать колонки в отчёте.

Ну и симпатичная, да:

UI

Все необходимые настройки и скрипты — в репозитории на Github'е; инструкция переведена на русский язык.

Ну, есть кое-какие
17 ноября 2025 ·
Тем временем

Гуляю вечером, сзади идёт какая-то мама и её мелкий — лет пяти, наверное. Я их не вижу, просто слышу разговор. Мама объясняет ребенку про университет: мол, туда надо поступить, учиться, будут экзамены и всё такое.

Мальчик молчит, потом расстроенно выдает:

— Я думал, есть только школа, а оказывается есть ещё сложности...

Безвредный вред
16 ноября 2025 ·
PostgreSQL
MS SQL

Разбирали на днях с коллегой проблему. Ничего особенно серьёзного, очередное расследование вида «какого черта этот запрос ведет себя странно?».

Упрощая, суть: читаем таблицу базы данных и кладем результат во временную таблицу. Если срабатывает определённое условие, нужно, чтобы временная таблица всё равно создавалась, но была пустой (независимо от того, есть строки в исходной таблице или нет).

Запрос был примерно такой:

SELECT
    Table.Field1 AS Field1
FROM
    Table AS Table
WHERE 
    &Parameter

Если нужно было отбирать записи из исходной таблицы во временную, в параметр передавался TRUE; если временную таблицу нужно было получить пустой — передавался FALSE.

Несмотря на кажущуюся простоту, такой трюк — проблема для производительности, если таблица, которую читает запрос — большая.

Причина в том, как СУБД работают с параметризованными запросами. И MS SQL, и PostgreSQL строят план выполнения запроса на основе его текста, и в примере выше значение параметра не повлияет на принятие решения, нужно читать таблицу или нет.

Таким образом, при выполнении такого запроса обе СУБД педантично прочитают всю таблицу (ну, или её индекс), даже если параметр равен FALSE. В последнем случае каждая прочитанная запись будет отброшена и алгоритм будет работать корректно, однако мы будем тратить ресурсы на бессмысленное чтение данных и забивать буферный кэш, замедляя систему в целом и активно работая на глобальное потепление :)

Решение тут простое — вставлять TRUE/FALSE в тело запроса как константу, не используя параметр. Либо использовать оператор TOP, так текст запроса будет даже проще:

SELECT TOP 0
    Table.Field1 AS Field1
FROM
    Table AS Table

Тут на уровне SQL мы получим что-то вроде «SELECT TOP 0 ... FROM Table» (для MS SQL) и «SELECT ... FROM Table LIMIT 0» (для PostgreSQL). В итоговом плане будет оператор чтения, но исполнитель фактически не запросит ни одной строки, так что реального сканирования данных не случится (ура).

P.S. Если не критично получать во временной таблице корректные типы колонок, можно вообще вот так:

SELECT TOP 0
    UNDEFINED AS Field1

Выигрыш в производительности, впрочем, будет таким копеечным, что можно не упарываться.

Шаманство
5 октября 2025 ·
Работа

Поймали, кажется, первый воспроизводимый в лабораторных условиях сценарий повреждения кэша платформы. Короткий синопсис:

  • Создаем новое приложение из шаблона 35-го релиза нашей ERP.
  • Запускаем его и ждем, когда закончится инициализация.
  • Заменяем конфигурацию приложения на 36-й релиз (конкретно, версию 28537 из хранилища разработки) и снова запускаем.

После этих нехитрых действий примерно у половины нашей команды платформа перестаёт видеть одно из перечислений. Причем, зараза, избирательно: обращаешься к элементу перечисления на клиенте — полный порядок, обращаешься на сервере — ловишь исключение.

Такая же петрушка с модулем менеджера одного из справочников: его методы недоступны, хотя существуют и объявлены как экспортные. Однако платформа после обновления делает вид, что их нет, и швыряется исключениями при попытке обратиться.

Welcome To Dipshit Central

Как и всегда, когда начинается магия — проблему нужно искать в кэше. Чистишь — все симптомы бесследно исчезают. Кроме того, есть и косвенные признаки:

  • Перечисление было и в 35-м релизе, но было переименовано в 36-м;
  • Методов в 35-м релизе вообще не было (в 36-м их как раз разработали).

То есть не первого, не вторых в кэше 35-го релиза не существовало, а платформа, по какой-то причине, пытается рыться в именно в нём.

Мы пока не доискались, что вызывает сбой. Вышли на конкретный коммит, после которого появилась проблема, но в нём из необычного — одно название (и то поблизости есть куда более подозрительные с этой точки зрения кандидаты). В остальном там минорные изменения, сопровождаемые заменой внутренних идентификаторов объекта метаданных. Они, конечно, связаны с ключами кэша, но их сброс делается при любом изменении любых метаданных и никогда раньше не приводил к проблемам.

Если вы набрели на эту заметку из гугла, потому что столкнулись с той же бедой — закиньте в проблемный объект какую-нибудь правку, чтобы платформа опять сменила идентификаторы объекта метаданных в манифесте. Например, добавьте пустой метод или просто пробел в текст модуля. Это решит проблему с конфигурацией и инструкция в начале заметки перестанет приводить к повреждению кэша.

Шаманство, конечно, но работает ¯\_(ツ)_/¯

Медленное удаление областей Фреша
3 августа 2025 ·
Работа

Коллега заметил, что на одном из инстансов нашего фреша удаление областей стало идти прямо-таки трагически долго. Что в метриках? Вот это:

DELETE FROM T1
FROM _DataHistoryMetadata T1
WHERE 
    T1._MetadataId = ?
    AND T1._IsActual = 0x00 
    AND NOT (
        T1._MetadataVersionNumber IN (
            SELECT T2._MetadataVersionNumber AS MetadataVersionNumber_
            FROM _DataHistoryVersions T2
            WHERE T2._HistoryDataId IN (
                SELECT DataHistoryLatestVersions1.DataHistoryLatestVersions._HistoryDataId AS HistoryDataId_
                FROM DataHistoryLatestVersions1.DataHistoryLatestVersions T3
                WHERE DataHistoryLatestVersions1.DataHistoryLatestVersions._MetadataId = ?
            )
        )
    )

Каждый такой запрос читает порядка двадцати гигабайт. Что тут происходит — примерно понятно: платформа пытается удалить историю данных области и кривой запрос к БД приводит к сканированию всей таблицы по всем областям вместо быстрого поиска по индексу. Кто-то на Дмитровском опять поленился.

Чему ты удивлён?

В общем, теряем от тридцати секунд до получаса на действие. Хотелось бы побыстрее. Решение:

CREATE NONCLUSTERED INDEX IX_DataHistoryLatestVersions1_MetadataId
  ON dbo._DataHistoryLatestVersions1 (_MetadataId)
  INCLUDE (_HistoryDataId)
  WITH (DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX IX_DataHistoryVersions_MetadataVersionNumber
  ON dbo._DataHistoryVersions (_MetadataVersionNumber)
  WITH (DROP_EXISTING = OFF, ONLINE = OFF);

Стоимость удаления области ожидаемо просела на ~99%.

Если будете повторять у себя:

  1. Формально такой трюк нарушает лицензионное соглашение, you've been warned и всё такое.
  2. Есть риск, что платформа при будущих реструктуризациях будет спотыкаться о новые индексы (особенно при работе по «новой» схеме). Лучше иметь под рукой готовый скрипт, который сможет их грохнуть, а потом (после реструктуризации) — вернуть обратно.
Развенчиватель мифов
27 июля 2025 ·

Попался под руку объёмный текст на Инфостарте про мифы о платформе, полез читать.

По сути. Половина там написана заголовка ради, кажется. Свежий номер! Криминал, интриги, расследования! Файловая база быстрее клиент-серверной! СКД медленнее запроса! Вызов метода сервера на сервере — новый вызов сервера! НЛО над Красной площадью!

Однако местами и правда любопытно. Например, о том, что код, слепленный в одну строку, механически работает в десять раз быстрее, я услышал впервые. Жалко, за такой отчаянный свэг коллеги побьют быстрее, чем успеешь порадоваться результату. Да и основные тормоза enterprise-приложений чаще растут из других мест.

Или, скажем, сравнение скорости выгрузки в таблицу для представлений объектов и для их наименований. Первое — в десятки раз медленнее! На первый взгляд странно: в конце концов, в обоих случаях у нас строки, и на момент замера они уже извлечены из базы. Думаю, что дело в типизации: строки представлений имеют неограниченную длину, в отличие от наименований. Отсюда расходы на выделение памяти, какие-то вспомогательные структуры и вот мы имеем то, что имеем.

P.S. Про некоторые аспекты из статьи я где-то у себя писал. Если навскидку — помню свою попытку измерить скорость работы ValueIsFilled() и неприятный сюрприз от встроенного FindByNumber().

Удаление геометрии
12 июня 2025 ·
3D

Освоил прикольный трюк с удалением части объекта в том случае, если он с чем-то пересекается. Например, на этой гифке в центре находится модель головы обезьянки; при движении плоскости видно, как её часть (как раз та, что начинает пересекаться с обезьянкой) исчезает.

Демо

Идея довольно простая: сводим геометрию объекта-ограничителя к кубу, вычисляем его минимальные и максимальные координаты по всем осям, а потом для каждой точки «обрезаемого» объекта проверяем, входит ли она в полученный диапазон. Входит? Удаляем.

Способов применения — масса; например, мне это пригодилось, когда я захотел автоматически отрезать часть линий декоративного нотного стана на стене так, чтобы они не пересекали дверной проем.

Пример

Конечно, можно было бы сделать это вручную, без геонод, но такой вариант ударил бы по гибкости: изменятся какие-то размеры (ширина стены, размеры двери, угол наклона линий) — всё придётся переделывать.

Нет
11 июня 2025 ·
Работа

Нет

Сообщение, которое выдает актуальная платформа при попытке подключения к выключенному кластеру серверов. Я, конечно, люблю лаконичность в интерфейсах, но тут всё-таки перебор.

Платформа, причем, установлена с единственным языковым пакетом (английским) и даже запущена с жестким указанием на «Ven VLen», но откуда-то всё равно прорастают родные березки. Возможно, сишная библиотека, откуда стреляет сообщение (DataExchangeTcpClientImpl.cpp) в моем случае смотрит на язык ОС (русский), сложно сказать.

В любом случае, не могу избавиться от ассоциаций с Багзом Банни каждый раз, как вижу это окошко.

No

Проблема джинна
12 апреля 2025 ·
3D

Вернувшись в Волькину комнату, Хоттабыч хитро оглянулся, щелкнул пальцами левой руки, и на стене... Тотчас же появилось точное подобие телефона, висевшего в прихожей.

— Теперь ты сможешь сколько угодно беседовать с друзьями, не покидая своей комнаты.

— Вот за это спасибо! — с чувством промолвил Волька, снял трубку, прижал ее к уху и долго тщетно прислушивался. Никаких гудков не было слышно...

— Аппарат испорчен, — объяснил он Хоттабычу, — сейчас я открою крышку. Посмотрим, в чем там дело.

Но коробка аппарата, несмотря на все усилия Вольки, никак не открывалась.

— Он сделан из цельного куска самого отборного черного мрамора! — похвастался Хоттабыч.

— Значит, внутри там ничего нет? — разочарованно спросил Волька.

— А разве внутри должно что-нибудь быть? — забеспокоился Хоттабыч.

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

«Старик Хоттабыч», Лазарь Лагин

Занимаясь 3D-моделированием, регулярно ощущаю себя этим джинном. Старик тоже пытался повторять форму предметов и даже делал их симпатичнее, как умел — однако фейлился, так как не понимал, что там внутри.

Вот и я так же. Последний месяц довожу до ума модель школьного класса музыки и знаете что? Об устройстве рояля я уже узнал больше, чем за всю предыдущую жизнь. А ещё могу прочитать короткую лекцию о системах отопления в российских школах: секционных батареях, панельных, чугунных и алюминиевых, какие чаще встречаются, расстояниях между ними, почему не надо подключать три в ряд и так далее :)

Я читал об этом эффекте: мол, рисуешь, например, самурайскую броню — по ходу дела волей-неволей много узнаешь о свойствах кожи, видах металла и технологическом стеке самурайской эпохи в целом. Не думал, правда, что столкнусь с этим буквально с самого начала — но, думаю, это хорошо. Стимуляция нейронных связей, расширение видения мира, развитие креативности и всё такое.

Ну и в целом интереснее работать с моделью, когда понимаешь, что там, так сказать, внутри барабанчика.

Пасхалки
6 апреля 2025 ·
Работа

Thank you, Mario!

Awaiting Signal

Пара пасхалок, которые можно найти внутри FirstBit ERP. Спрятаны для разработчиков: пользователи в первом случае видят на форме заголовок и текст оповещения, а во втором — стандартное waiting for connection.

Люблю время от времени делать такие штуки: это весело, а ещё — помогает не скучать, даже если задача не слишком увлекает или просто устал. Если не читали заметку «Дизайн без стресса» Быстроновского — прочитайте, она клёвая (а я все равно не сформулирую лучше).

Вот, кстати, ещё одна пасхалка. Эта уже не из нашей ERP, а из нового инструмента по автоматическому обновлению баз. Его мы пишем сами для себя, поэтому можно хохмить с пользователем :)

Nice try, Marty!

Разработка ERP на английском
19 января 2025 ·
Работа
English

Ведущий разработчик из нашей команды немного рассказал о нашей работе — конкретно, о разработке ERP на 1С для ОАЭ и, с недавних пор, Саудовской Аравии. Встречу захостила онлайн-школа английского языка Across, так что аудитория получилась соответствующая — русскоговорящие ребята, интересующиеся карьерой и рынками за рубежом.

В целом получилось прикольно, особенно как языковая практика. Напоминаю, что изучение иностранных языков — все ещё один из лучших способов размять мозги и, до кучи, один из самых доступных. Материалов и клубов по интересам не найти невозможно, было бы желание :)

Загадочный код
18 января 2025 ·
Грузия
Видеоигры

Код

Где-то на улицах Тбилиси. Как большой фанат серии Dishonored — не смог пройти мимо. Уверен, поблизости есть сейф, к которому этот код подходит!

Уходи, негатив!
29 декабря 2024 ·
Грузия
Тем временем

Чичилаки

Белые штуки на заднем плане называются чичилаки. Это что-то вроде грузинской новогодней ёлки (де-факто, тщательно наструганный орешник). Считается, что он собирает на себя весь накопившийся негатив, так что после праздников его положено сжечь (вместе с негативом).

Последнее, как оказалось, задача со звездочкой. Местная полиция (и особенно пожарка) относится к этой старой доброй традиции с подозрением, и их можно понять (чичилаки бывает и в рост человека, факел выйдет — будь здоров). Так что «заряженную» негативом чичилаки нам посоветовали просто выкинуть в мусорку, чтобы не нажить свежих проблем. Или сдать в зоопарк: животные ими играют и зубы чистят.

Последнее позабавило. Избавиться от негатива помогают котики, какая неожиданность. Да, здоровенные и повышенной зубастости, но всё же!

Немного хирургии
17 декабря 2024 ·
Работа

Несколько лет назад попадалась на глаза заметка программиста, которому пришлось отлаживать ПО, управляющее роботом-хирургом, прямо во время операции. Помню, тогда это меня поразило до глубины души.

А сегодня с коллегой ремонтировали кластер 1С с базами на 1cFresh, которому после миграции на соседний сервер внезапно поплохело (если вкратце, при попытке распечатать документ клиентское приложение умирало в муках). Пока возились, мелькнула мысль: это, конечно, не так жутко выглядит, как ремонтировать софт, от которого вот прямо сейчас зависит чья-то жизнь, но... Если посчитать всех клиентов, которые вот прямо сейчас сидят на нервах из-за того, что у них бизнес стоит — ещё неизвестно, где уровень стресса будет выше.

P.S. Технические заморочки для тех, кому интересно. Вышло так, что при миграции кластера права на папку с серверным кэшем переехали некорректно и это привело к любопытному эффекту: в ней оседали только логи, а данные сеансов — нет. В итоге при открытии печатной формы документа конфигурация пыталась положить её в хранилище; rphost, в свою очередь, пытался засунуть её в серверный кэш сеанса.

Так что рабочий процесс (видимо) получал по рукам от ОС, из-за (видимо) кривой отработки событий файловой системы в платформе никак это исключение не обрабатывал и от безысходности убивал сеанс, что, в свою очередь, приводило к крашу клиентского процесса.

Пересобрали права, перезапустили кластер, проблема ушла.

End of Report

Остальные гипотезы (буйство менеджера кластера, недостаток аппаратных ресурсов, программные ошибки конфигурации, ошибки клиентского процесса, кривая отработка security profile, проблемы c сетью между клиентом и сервером) отбросили по ходу диагностики.

Смутно знакомый логотип
14 декабря 2024 ·
ИИ
Грузия

Тем временем OpenAI открыл в Тбилиси филиал На самом деле тут вейпами торгуют, а дизайнер логотипа, скорее всего, вдохновлялся клубами пара. Но каждый раз, как мимо хожу, глаз цепляется :)

Vaporia

Жуткое кладбище
26 ноября 2024 ·
3D
Готово

Продолжаю осваивать 3D в свободное время. Вот, первая более-менее самостоятельная работа с курса, который недавно закончил.

Creepy Graveyard

Проблем, конечно, хватает: и в моделях, и в цветах, и в композиции... Да вообще везде. Хорошо хоть, что сцена по сюжету — ночь и туман. Самые косячные места можно просто спрятать. Не удивлюсь, если авторы курса специально выбрали такой сеттинг, чтобы новички не расстраивались :)

Но результатом я всё равно доволен. Думаю, на этом этапе перфекционизм скорее мешает, чем помогает. К тому же получилось явно лучше, чем прошлая работа. Я тогда был совсем зелёным в Blender и боялся сделать шаг в сторону от преподавателя: десять минут смотрел урок, а потом десять минут пытался повторить.

Такой подход работает только на старте, но не помогает понять, как искать решения проблем. Поэтому в этот раз я смотрел несколько уроков подряд по часу-полтора. Потом пробовал делать сам и к видео возвращался, только если совсем что-то не клеилось. В голове, кажется, осело заметно больше.

Короче, прогресс есть, едем дальше!

UPD: Один из фаундеров FlippedNormals записал ролик с теми же мыслями про обучение.

Сводка в Slack
10 ноября 2024 ·
Работа
Готово
Powershell

Попался под руку скрипт, который я пару лет назад накатал для рабочего GitLab'а. Вкратце: мы ежедневно прогоняем репозиторий разработки через прорву тестов на Ванессе, в результате чего получаем симпатичный отчет — сколько тестов выполнено, какие провалились, причины провалов и так далее.

Отчет нужно постоянно анализировать, хотя бы бегло. Конечно, полностью «зеленых» тестов мы уже давно не видели, и это нормально: например, в случае взаимозависимой разработки, когда коммиты ломают проверяемый функционал, и тесты еще предстоит поправить. Однако держать руку на пульсе все равно необходимо.

Чтобы упростить эту рутину, я немного расширил код пайплайна: после формирования отчета GitLab первым делом создает короткую сводку (тип клиента, тип базы, статистика по тестам) и отправляет ее в слак.

Отчет

Как бонус, стало проще отвечать на философский вопрос «кто все сломал». Чаще всего — автор первого коммита, на котором метрика Scenarios Failed на скриншоте выше пробила потолок :)