гейт судит staged-файлы; рендер диаграмм пошёл параллельно
Гейт проверял рабочее дерево целиком — то есть не то, что уедет в историю, а
то, что лежит на диске рядом. Плюс платил за это временем: пятнадцать секунд на
каждый коммит с правкой markdown, потому что одиннадцать блоков рендерились по
очереди, каждый своим запуском mermaid-cli со своим chromium.
diagrams.py научился двум вещам. Первая — принимать файлы списком: без
аргументов обходит репозиторий как раньше, с аргументами смотрит только
названные, отбирая из них markdown внутри корня (гейт передаёт весь staged, где
есть и скрипты, и удалённое). Вторая — рендерить пулом потоков: работа целиком в
ожидании подпроцесса, своего интерпретатора ей не надо, а потолок в восемь
воркеров упирается в память chromium, а не в двадцать четыре ядра. Порядок
находок берётся из порядка сбора, не из порядка ответов, так что вывод
детерминирован. Весь репозиторий — 3 секунды вместо 15, один файл — 1.
В хуке теперь {staged_files} у диаграмм, ruff и pyrefly. Два исключения
остались, и оба по существу: copies.py сверяет копию с домом, а дом лежит в
другом файле, которого в индексе может не быть — список staged дал бы «копии
дословны» ровно там, где правка дома их и разошлась; frontmatter.py обходит всё
за сотые доли секунды, экономить нечего. Оба объяснены прямо у своих задач.
ruff встал с --fix и stage_fixed: безопасное чинится само и доносится до этого
же коммита. Иначе исправленный файл оставался бы в рабочем дереве, а в историю
уезжал бы невычищенный — гейт зелёный, коммит грязный.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -312,13 +312,19 @@ uv run python scripts/copies.py # 0 сошлось, 1 расхождение
|
||||
правдоподобно, диff показывает разумную строку, а рендер падает.
|
||||
|
||||
```
|
||||
uv run python scripts/diagrams.py # 0 рендерятся, 1 нет, 3 нет mermaid-cli
|
||||
uv run python scripts/diagrams.py # весь репозиторий
|
||||
uv run python scripts/diagrams.py A.md B.md # только названные файлы
|
||||
# 0 рендерятся, 1 нет, 3 нет mermaid-cli
|
||||
```
|
||||
|
||||
Рендерит `mmdc` с PATH или `npx --yes @mermaid-js/mermaid-cli`; ни того ни
|
||||
другого нет — код 3, а не молчаливый успех. Прогон занимает секунды на блок —
|
||||
это самая дорогая из трёх проверок, и в гейте коммита она стоит **под glob по
|
||||
markdown**: правка одних скриптов проходит мгновенно.
|
||||
другого нет — код 3, а не молчаливый успех. Это самая дорогая проверка
|
||||
репозитория: каждый блок — отдельный запуск mermaid-cli со своим chromium,
|
||||
секунда с лишним. Поэтому у неё два рычага, и оба нужны гейту коммита: **блоки
|
||||
собираются все сразу, а рендерятся параллельно** (пул потоков, порядок вывода
|
||||
берётся из порядка сбора), и **проверять можно названные файлы, а не весь
|
||||
репозиторий**. Весь репозиторий — три секунды вместо пятнадцати, один
|
||||
файл — одна.
|
||||
|
||||
Чего проверка **не** ловит — расхождение диаграммы с прозой вокруг неё. Дословного
|
||||
соответствия между текстом и графом нет, сличать нечего, и держится это
|
||||
@@ -336,25 +342,27 @@ lefthook install # пишет .git/hooks/pre-commit
|
||||
lefthook run pre-commit # прогнать руками, не коммитя
|
||||
```
|
||||
|
||||
| Проверка | Когда идёт | Сколько |
|
||||
| --- | --- | --- |
|
||||
| фронтматтеры | правка `*.md` | миллисекунды |
|
||||
| копии правил | правка `*.md` | миллисекунды |
|
||||
| диаграммы | правка `*.md` | ~15 с на весь репозиторий |
|
||||
| `ruff check .` | правка `*.py` | доли секунды |
|
||||
| `pyrefly check` | правка `*.py` | доли секунды |
|
||||
| Проверка | Когда идёт | Что смотрит | Сколько |
|
||||
| --- | --- | --- | --- |
|
||||
| фронтматтеры | правка `*.md` | весь репозиторий | миллисекунды |
|
||||
| копии правил | правка `*.md` | весь репозиторий | миллисекунды |
|
||||
| диаграммы | правка `*.md` | staged-файлы | ~1 с на файл |
|
||||
| `ruff check --fix` | правка `*.py` | staged-файлы | доли секунды |
|
||||
| `pyrefly check` | правка `*.py` | staged-файлы | доли секунды |
|
||||
|
||||
Glob разводит две половины: коммит, трогающий одни скрипты, не платит за рендер
|
||||
диаграмм, а коммит в документы не гоняет линтеры. Внутри своей половины
|
||||
проверяется **весь репозиторий**, а не изменённые файлы: и расхождение копии, и
|
||||
находка ruff в соседнем файле — это ровно тот случай, когда правка сломала не
|
||||
себя.
|
||||
диаграмм, а коммит в документы не гоняет линтеры.
|
||||
|
||||
Два свойства, о которых стоит знать заранее:
|
||||
**Судятся staged-файлы, а не рабочее дерево** — гейт обязан проверять то, что
|
||||
уедет в историю, а не то, что случайно лежит рядом на диске. Исключений два, и
|
||||
оба про существо, а не про удобство: `copies.py` сверяет копию с домом, а дом
|
||||
лежит в другом файле, которого в индексе может не быть (список staged дал бы
|
||||
«копии дословны» ровно там, где правка дома их и разошлась), а `frontmatter.py`
|
||||
обходит весь репозиторий за сотые доли секунды — экономить тут нечего.
|
||||
|
||||
- **судится рабочее дерево, а не индекс.** Скрипты обходят репозиторий целиком
|
||||
и про `git add` не знают: частичный коммит при грязном дереве проверяется по
|
||||
тому, что на диске. Это цена того, что проверки — обход, а не фильтр файлов, и
|
||||
она принята: расхождение копий и битая диаграмма ловятся именно обходом;
|
||||
- **обход разовый — `LEFTHOOK=0 git commit …`.** Он законен ровно для случая,
|
||||
когда найденное нечем чинить прямо сейчас; молча пропущенная проверка — нет.
|
||||
**`ruff` чинит безопасное сам, и починка доносится до этого же коммита**
|
||||
(`stage_fixed: true`). Иначе исправленный файл остался бы в рабочем дереве, а в
|
||||
историю уехал бы невычищенный — худший из исходов: гейт зелёный, коммит грязный.
|
||||
|
||||
**Обход разовый — `LEFTHOOK=0 git commit …`.** Он законен ровно для случая,
|
||||
когда найденное нечем чинить прямо сейчас; молча пропущенная проверка — нет.
|
||||
|
||||
Reference in New Issue
Block a user