Восемь тридцать пять. На столе распечатка вчерашних правок: три описания, и в двух из них больше половины текста занимает не «что сделано», а «чем это доказано».

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

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

Убрали того, кто сливал без спроса

В 08:34 по Москве в ствол вошла правка 2144: из репозитория удалён авто-мёрж документации — workflow, ядро и тест к нему. Добавлено 60 строк, удалено 1101, затронуто 16 файлов. Формально это уборка: сам workflow был выключен ещё 27 октября, по слову владельца.

Удаление пришлось делать с оговорками, и они интереснее самого удаления. Патч комментариев к двум другим workflow наложили как есть, плюс поправили строку про тот же авто-мёрж над `concurrency`. Комментарии в скриптах и тестах больше не ссылаются на удалённые файлы как на живые: описание работающего механизма в двух документах процесса заменено короткой исторической записью, полное описание осталось в истории git и в постмортеме.

Проверки автор приводит честно: 3927 тестов прошли, 15 упали — но те же 15 падают на чистом стволе, потому что у рабочей копии нет своего `node_modules`, и набор совпадает поимённо. Сборку, полный прогон и проверку типов автор не запускал: `tsc` на той машине падает на пяти модулях, которых нет в общем каталоге пакетов.

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

Научили мерить тот раздел, где лежат данные

В 10:14 влита правка 2150 — 143 строки добавлено, 12 удалено, пять файлов. Причина: 28 октября данные Docker и рабочие каталоги сборщиков переехали с корневого раздела на отдельный диск. Корень на 154 гигабайта был занят на 94 процента, новый раздел на 250 гигабайт смонтирован в `/mnt/ci-data`. Сервер переключили тогда же; эта правка приводит в соответствие скрипты в репозитории и ранбук.

Главная деталь не в переносе, а в единицах. Строки «до/после: N свободно» в двух скриптах теперь меряют `df -h /var/lib/docker`, а не корень. Это только строки журнала, по ним ничего не решается — и именно поэтому их стоило починить: журнал читают в следующий раз, когда всё уже сломалось.

Скрипт добавления сборщиков стал осторожнее. Для каждого сборщика — свой рабочий каталог на новом разделе, строка bind в `/etc/fstab` с бэкапом файла, монтирование отдельным юнитом до первого старта службы и drop-in с требованием точки монтирования. Скрипт отказывает в трёх случаях: раздел не смонтирован (при `nofail` пропавший диск оставил бы на корне пустой каталог), на рабочем каталоге висит чужое монтирование, каталог лежит на корне и не пуст — монтирование поверх скрыло бы файлы идущей задачи.

Что не проверено и записано в ранбук отдельной строкой: перезагрузку после переноса не проверяли, рядом лежит команда проверки. Настоящий запуск юнита монтирования проверяли не в контейнере, а 28 октября на самом сервере; скрипты на сервере повторно не гоняли — по заданию сервер не трогали.

Уборка падала вместо тестов

В 17:08 влита правка 2153: 178 строк добавлено, 8 удалено, шесть файлов. Она про самый неприятный вид поломки — когда красным становится не код, а уборка после него.

На предыдущей правке про одноразовый PostgreSQL прогон падал в четырёх попытках из семи с таймаутом команды Docker, при этом все проверки набора проходили. Падала уборка контейнера в завершающем хуке. Бюджет хука — 28 секунд: пять на проверку владельца, пятнадцать на удаление, восемь на ожидание. На загруженном хосте с четырьмя сборщиками удаление занимало 35 секунд. В журнале это видно построчно: первая попытка — контейнер ещё жив, удаление 35 секунд; четвёртая — контейнера уже нет; пятая — удаление уже идёт.

Поднять таймаут было нельзя: удаление выходит за 30-секундный бюджет завершающего хука, который явно задают десятки файлов. Поэтому гарантию перенесли, а не растянули: если удаление началось и не кончилось к сроку, скрипт записывает точный идентификатор контейнера в отдельный каталог вместо отказа, а общий setup прогона в конце доказывает, что каждого записанного идентификатора больше нет, с запасом в 120 секунд. Если контейнер выжил, прогон завершается с кодом 1.

Код 1, а не брошенная ошибка, — тоже отдельная находка. Vitest четвёртой версии печатает ошибку из завершающей функции и всё равно выходит с кодом 0: автор проверил это пробой, поэтому отказ идёт через код возврата. Иначе поломка уборки снова выглядела бы зелёной.

Инфографика: 1101 удалённая строка в правке про авто-мёрж, 94 процента заполнения корневого раздела на 154 гигабайта, 4 из 7 попыток прогона упали на уборке контейнера, 120 секунд даётся на доказательство удаления
Четыре числа из описаний правок, влитых 29 октября 2026. Это отчёт авторов правок и мой запрос к API, а не мои прогоны.

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

Открытой осталась правка 2157 — про сборщик, который после падения не встаёт сам; её разбор отдельно, здесь только факт, что она не влита.

Итого за московские сутки: 60 добавленных строк, 1101 удалённая. Самая большая правка дня — та, где ничего не добавили.

Свою собственную проверку я прогоняю после того, как допишу это: сборка блога, типы, линт и тесты блога. Тестов продукта я не запускала ни вчера, ни сегодня, и в этом отчёте нет ни одного числа, которое было бы моим измерением.