Правило, которое почти работает
Дисциплина «состояние читаем из основной ветки» закрывает самый частый провал — работу по устаревшему диску. Дальше она превращается в ловушку: правило звучит абсолютно, а верно только для того класса фактов, который в этой ветке действительно хранится.
| Носитель | Что там правда | Чего там нет |
|---|---|---|
| Рабочая копия на диске | То, над чем идёт работа прямо сейчас | Всё, что приехало в общую ветку после создания копии |
| Файл доски в общей ветке | Тексты и метаданные карточек | Статусы: их проставляют через инструмент, и пишутся они на сервер |
| Серверный слой панели | Статус, взятые задачи, входящее от владельца | Ничего — для статуса это решающий носитель |
Слои уточняют друг друга по порядку, и каждый следующий отменяет предыдущий только в своей части. Ошибка была не в коде инструмента — он умел ходить в серверный интерфейс с самого начала. Ошибка была в раздаваемом правиле.
Диск против ветки: «новый файл» оказался окаменелостью
Приёмка чата началась с соблазнительной картины: статус общего дерева показал три позиции как неотслеживаемые — страница разбора, обработчик к ней и каталог с аудио. Читается однозначно: человек работал, забыл закоммитить, надо спасать.
Оба файла уже лежали в основной ветке, а на диске были версии двухнедельной давности — общее дерево стояло на старой ветке, где этих файлов ещё не существовало. Статус «неотслеживаемый» читается как «в системе контроля версий такого нет», хотя означает «нет в той точке отсчёта, на которой я стою».
Чем грозило «спасение». Откатом фикса безопасности. Дисковая версия обработчика заявляла защиту, снятую при переходе двумя неделями раньше, а хранилище вердиктов уехало бы обратно в каталог, где правило запрета не срабатывает: перечень расширений построчный, и формат построчного журнала под него не подпадает. В файлах — расшифровки клиентских голосовых. В версии из основной ветки было на 12 строк больше, и все двенадцать — про авторизацию.
Проверка занимает одну команду: содержимое из основной ветки подаётся на вход сравнению с дисковым файлом, отдельно сверяются даты. Дисковая версия старше — это не работа, а окаменелость. Направление правки видно по диффу: если строки, которых нет на диске, содержат проверку прав или запрет доступа, «спасение» снимает защиту.
Репозиторий против прода: правило, которого на сервере не было
Постановка описывала дефект так: файл-сирота отдаёт код 200 и глушит правило переадресации из конфига сервера, значит файл надо удалить. Проверка показала другую картину — правила на проде не было вовсе, оно приехало тем же коммитом партии, который так и не выкатили.
Почему удаление сделало бы хуже. Без правила снос сироты даёт 404 вместо 301: адрес уже в индексе, а вес не передаётся никуда. Правило и удаление файла — две половины одного фикса, и едут они разными каналами: правило выкладкой, удаление отдельной командой на файловом доступе. Порядок обязателен: сначала правило, потом удаление, иначе между ними окно с 404.
Ловушка тут в невидимости: конфиг сервера обычным запросом не читается, прод отдаёт на него 403. Когда состояние снаружи не видно, по умолчанию подставляется состояние репозитория — не по злому умыслу, а потому что другого под рукой нет. Лечится чтением прод-версии по файловому доступу и сравнением с репозиторием.
Проверку мы сделали частью самой операции: инструмент печатает код ответа до и после и валит прогон, если ожидание не сбылось. Здесь было 200, стало 301. Побочный результат того же захода дороже основного: прод-версия конфига совпала с репозиторием байт в байт — правок мимо репозитория не было, лить безопасно.
Терминал против файла: доказательство обязано пережить чат
Страницу прогнали чекером дважды — до правок и после, оба раза «критичных 0». Ход всё равно заблокировали: «правленые страницы не подтверждены чекером, отчёта нет». Без флага записи чекер печатает результат в терминал и не кладёт на диск ничего, а гейт читает файл отчёта, а не наш рассказ. Для гейта проверки не существовало.
Гейт прав по существу. Разрыв тот же, что в правиле «отчёт в чат = отчёта нет», только внутри одной сессии: результат жил в контексте, который исчезнет вместе с чатом. Обход — гнать чекер сразу с записью отчёта, а осознанный пропуск оформлять флагом-исключением с коротким сроком жизни и обоснованием, а не молчанием.
Что делать у себя
- На каждый повторяющийся вопрос — один решающий носитель и одна команда. «Статус задачи», «состояние прода», «содержимое страницы» — выписать явно, иначе каждый спросит ближайшую копию.
- В отчёте писать, чем считано. Пока расхождение слоёв не устранено механизмом, любое число обязано нести способ замера — иначе два честных отчёта разойдутся и спор будет ни о чём.
- Мерить расхождение, а не верить в его отсутствие. Сравнение двух множеств открытых задач — из файла и из инструмента — заняло минуты и дало 32 и 37.
- Невидимое снаружи читать по другому каналу. Конфиги, права, серверные переменные не отдаются обычным запросом; вместо догадки — файловый доступ и дифф с репозиторием.
- Доказательство класть на диск. Проверка, результат которой остался в переписке, для любого гейта и любого преемника не выполнялась.
Ни в одном из четырёх случаев данные не врали. Врал выбор носителя, к которому обратились, — и каждый раз это была ближайшая копия, а не та, что решает.