feat(max-filename-words): хук потолка слов в имени модуля (grandfather от merge-base) #7
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feature/max-filename-words"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Реализация ADR-0025 §7 (senokosov/baton#1307). Новый хук
max-filename-wordsрядом сno-underscore-filenames.Что делает
Имя
.py-модуля не длиннее N значимых слов (envMAX_FILENAME_WORDS, дефолт2). Стем без.py, ведущийtest_отброшен, split по_, пустые сегменты не в счёт. Истинный dunder (__init__.py, …) иconftest.py— skip. Меряет число слов, не символов:taskinstanceок,org_repo_host_config— нет.Grandfather от базовой ревизии (тот же механизм, что у
check-file-lengthсv0.13.0): FAIL только на файле, НОВОМ относительно базы (добавлен или переименован-в-длинное). Уже существующий там длинный файл —WARN(grandfather), коммит разрешён. База зависит от способа вызова: в CI-инвокацииpre-commit run --from-ref X --to-ref Y— merge-baseXиY, в обычном commit-хуке и при--all-files—HEAD. Вне git — FAIL. Скоуп и точечные исключения —files:/exclude:у consumer'а.Файлы
scripts/check_max_filename_words.py+ console-scriptcheck-max-filename-wordsвpyproject.toml.pre-commit-hooks.yaml:id: max-filename-wordsfixtures/filename_words/+ smoke-кейсы,fixtures/check_grandfather_baseline.sh+ 4 кейса CI-инвокацииREADME.md,examples/.pre-commit-config.example.yaml: секция хука, пример конфига, пинv0.14.0Что изменилось после первого ревью
Первая редакция брала за базу
HEADи в CI отдавала зелёный вхолостую. В инвокацииpre-commit run --from-ref/--to-ref(так гоняют все консьюмеры) рабочее дерево уже стоит на проверяемом коммите, поэтомуHEAD:pathсуществует у любого добавленного веткой файла: grandfather срабатывал всегда, и новый длинноимённый модуль проезжал зелёным — то есть хук не делал ровно того, ради чего заведён. Тот же класс бага, что вылечен в #15 дляcheck-file-length; здесь он пойман до релиза.Smoke этого не видит по построению — он зовёт скрипт напрямую списком файлов, где
HEADи так «старая» версия. Поэтому проверка живёт вfixtures/check_grandfather_baseline.sh, который поднимает настоящий репозиторий и зовётpre-commitкак CI: новый длинноимённый файл, правка legacy-модуля без переименования, переименование короткого имени в длинное, локальный commit-хук. Возврат базы наHEADроняет два кейса из четырёх.По второму ревью:
.*/alembic/versions/.*в примере конфига не исключал плоскую раскладкуsrc/alembic/versions/...(имя ревизии автогенерируется многословным, а файл миграции всегда новый — grandfather не спасает никогда), поправлено на(.*/)?…; пофайловые WARN печатаются перед сводкой; мусор вMAX_FILENAME_WORDSдаёт вердикт, а не трейсбек; кейс dunder-скипа перестал быть вакуумным; words-кейсы гейта ветвятся от собственной базы.Верификация
bash fixtures/run_smoke.sh— все кейсы зелёные (16 в секции хука).bash fixtures/check_grandfather_baseline.sh— 12 кейсов, включая 4 новых; мутация (база обратно наHEAD) роняет ровноci_new_long_name_failsиci_rename_to_long_fails.python3 fixtures/check_wheel_matches_sources.py— колесо несёт текущие исходники.backend/core+backend/modules) →exit=0: grandfather не валит существующий долг.Версия
0.13.0→0.14.0: новый хук, minor.После мержа — за @volody (релизные шаги)
Тег
v0.14.0и его push. Отдельно: на remote нет теговv0.10.0–v0.13.0, хотя README пинитrev: v0.13.0— консьюмер такой пин не зарезолвит. Заведено отдельной задачей.В
senokosov/baton— bumprev:и регистрация инстансаmax-filename-wordsсо скоупом под текущую раскладку (backend/core/backend/modules, excludedb/models/alembic/versions/proto/generated) отдельным PR, по команде. Скоуп из тела baton#1307 (backend/baton) устарел после модульного рефактора.Независимое ревью (субагент, свежий контекст): APPROVE, блокеров нет. Диспозиция нитов:
2b5091b): dunder-скип сужен до истинного__…__.py(не любой ведущий__) + smoke-кейс.2b5091b): README-пример consumer-конфига исключаетalembic/versions+proto/generated(автоген-имена многословны → иначе гарантированный FAIL при копировании примера).MAX_FILENAME_WORDS— оставлена fail-loud (нечисловое →ValueError; отрицательное = мисконфиг, не рантайм-риск).Smoke: 11/11 кейсов зелёные (
bash fixtures/run_smoke.sh→ All smoke cases passed). Прогон по дереву baton (394 файла) → exit 0, grandfather не валит существующее.Тот же класс бага, что чинится в #15 — здесь он ещё не выпущен, поэтому ловим до релиза, а не после.
scripts/check_max_filename_words.py:42определяет «файл уже был» так:В настоящем git pre-commit-хуке это верно: новый коммит ещё не создан, файла в
HEADнет → FAIL, как и задумано. Но в CI-инвокации (pre-commit run --from-ref X --to-ref Y, так гоняют все четыре консьюмера) рабочее дерево уже стоит на проверяемом коммите, и любой файл, добавленный в MR, вHEADприсутствует. Значит_in_head()вернётTrue, сработает grandfather, и новый модуль с длинным именем проедет зелёным — то есть хук не сделает ровно того, ради чего заведён.Проявляется это только в способе вызова, поэтому текущие смоук-кейсы его не увидят: они дёргают скрипт напрямую списком файлов.
В #15 лечится так: базовая ревизия берётся из
PRE_COMMIT_FROM_REF/PRE_COMMIT_TO_REF(pre-commit выставляет их ровно в этом режиме) как merge-base, иHEADостаётся только там, где он действительно означает «до правки». Merge-base, а не вершина from-ref, — иначе переименование, приехавшее в целевую ветку после ветвления, засчитается текущему MR.Перед мержем этого PR стоит сделать то же самое, причём после #15 — там появится
fixtures/check_grandfather_baseline.sh, который поднимает настоящий репозиторий и зовёт pre-commit как CI; по его образцу проверка этого хука пишется в несколько строк. Заголовок PR («grandfather по HEAD») тогда тоже перестанет быть точным.2b5091bef076494a255cfeat(max-filename-words): хук потолка слов в имени модуля (grandfather по HEAD)to feat(max-filename-words): хук потолка слов в имени модуля (grandfather от merge-base)