Можно ли не допустить в репозиторий код 1С с ошибками? Хук для git, который проверяет конфигурацию платформой до коммита
Разработка - Групповая разработка (Git, хранилище)
Файлы
ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.
Подписка PRO — скачивайте любые файлы со скидкой до 85% из Базы знаний
Оформите подписку на компанию для решения рабочих задач
Оформить подписку и скачать решение со скидкойВы можете заказать платную доработку или адаптацию этой разработки под вашу конфигурацию на «Бирже заказов».
- 0% комиссии — оплата напрямую исполнителю;
- Исполнители любого масштаба — от отдельных специалистов до команд под проект;
- Прямой обмен контактами между заказчиком и исполнителем;
- Безопасная сделка — при необходимости;
- Рейтинги, кейсы и прозрачная система откликов.
Проверка перед коммитом полезна, если платформа получает именно ту конфигурацию, которая записана в индексе. В комплекте исправленный хук, сценарии и журналы обеих версий.
- Хук загружает полный снимок индекса в новую временную базу; загрузка только изменённых файлов в накопленную базу этого не обеспечивает.
- Платформа остановила синтаксическую ошибку и повреждённый XML.
- Вызов несуществующей процедуры общего модуля проходит с ключами по умолчанию и останавливается, если добавить в HOOK_CHECKS ключ -ExtendedModulesCheck. Лишний аргумент при вызове другого модуля прошёл в обоих режимах.
- Цена: 30-33 с на коммит с изменёнными модулями на «Нано-УТ 2.0».
- Ключ --no-verify обходит хук, поэтому серверная проверка нужна отдельно.
Локальная проверка платформой до коммита останавливает часть ошибок сразу у разработчика, но серверную проверку не заменяет.
Для кого: разработчики 1С, которые хранят выгрузку конфигурации в Git и готовы оплачивать локальную проверку временем ожидания.
Разработчик добавляет в индекс модуль с синтаксической ошибкой. Без локальной проверки об этом сообщает уже сборка на сервере. Я проверила, что может остановить такой коммит на компьютере разработчика, и обнаружила ошибку в первой реализации собственного хука.
Стенд
| Условие | Значение |
|---|---|
| Платформа | 1С:Предприятие 8.3.27.2130 x86, пакетный Конфигуратор |
| Исходники | «Нано-УТ 2.0», 81 BSL и 212 XML; исходное дерево восстановлено из базового коммита стенда |
| Инструменты | Git for Windows 2.56.0.windows.1, Python 3.12.10, стандартная библиотека |
| Компьютер | Windows 11 Pro, Intel Core i5-2400, 7,9 ГБ ОЗУ, SATA SSD; рабочая машина с открытыми приложениями |
| Метод | Настоящие git commit в отдельном тестовом репозитории; время измерено скриптом |
Это отдельные измерения на небольшой конфигурации. Они не дают оценки скорости на УТ или ERP и не доказывают независимость времени от количества файлов.
Что пришлось исправить
Первая версия загружала HEAD один раз, а потом обновляла служебную базу файлами очередного коммита. У такой схемы нашлись три проблемы.
По умолчанию разные репозитории использовали один каталог базы. После перехода на другую ветку база также могла сохранить чужое состояние. При обходе хука изменения в неё не попадали. Поэтому правильные версии отдельных файлов ещё не означали правильную конфигурацию целиком.
При отказе хук пытался вернуть файлы из HEAD, но не проверял результат обратной загрузки. У нового файла версии в HEAD вообще нет. Следующая проверка могла получить остатки неудачной попытки.
Сценарий опыта удалял существующий каталог --work. Теперь он принимает только новый путь и завершает работу с ошибкой, если каталог уже существует.
В версии 2 накопленная база исключена. Каждый запуск создаёт свою временную базу, загружает полный снимок индекса и удаляет только собственный временный каталог. Возвращать файлы в прежнее состояние больше не требуется.
Как работает версия 2
- Хук ищет изменения BSL/XML в указанном каталоге выгрузки, включая удаления и переименования. Если таких изменений нет, проверка пропускается.
- Команда git write-tree фиксирует дерево индекса. Из этого дерева извлекаются все файлы выгрузки. Незакоммиченные правки рабочего каталога не подмешиваются.
- В отдельном временном каталоге создаётся файловая база через CREATEINFOBASE.
- Пакетный Конфигуратор выполняет полную /LoadConfigFromFiles и затем /CheckModules с параметрами -ThinClient -Server -ExternalConnection.
- Ненулевой код любой стадии останавливает коммит и выводит диагностику. Перед успешным завершением хук повторно сверяет дерево индекса: если оно изменилось во время проверки, коммит надо повторить.
- Временный каталог удаляется. Если удалить его не удалось, хук печатает путь; следующий запуск создаёт другую базу.
Настройка HOOK_IB из старой версии больше не используется. Старые пользовательские базы хук не открывает и не удаляет. Символические ссылки и Git-подмодули внутри каталога выгрузки не поддерживаются.
Подключение
Нужны Windows, Git for Windows, Python 3.12+ с командой python в PATH и установленная платформа с доступной лицензией.
Скопируйте hook/pre-commit и hook/check_staged.py из архива в каталог .githooks своего репозитория. Для выгрузки в src создайте .1c-hook.json:
Настройка читается из индекса; её можно заменить переменной HOOK_SRC. Если у проекта уже есть хуки, объедините их перед изменением core.hooksPath. Команду подключения выполняет каждый разработчик в своём клоне.
В PowerShell укажите установленную платформу:
Добавьте в индекс полную выгрузку, измените комментарий в модуле и сделайте коммит. Хук напечатает идентификатор проверенного дерева, результат и полное время выполнения. Подробности и остальные переменные окружения перечислены в README.md.
Рис. 1. Снимок окна терминала: коммит с правкой комментария прошёл, хук проверил снимок индекса из 293 файлов за 41,2 с (повторный прогон 23.10)
Что остановила платформа и что пропустила
Удаление КонецЦикла из модуля ЦеныУчет останавливает коммит. Диагностика содержит имя модуля, строку и ожидаемое ключевое слово. Вызов НеизвестнаяПроцедура123(1) без имени другого модуля также обнаружен. Обрезанный Catalogs/Склады.xml останавливает загрузку ещё до проверки модулей.
Рис. 2. Снимок окна терминала: коммит без КонецЦикла остановлен, платформа назвала модуль и строку (44,1 с)
Рис. 3. Снимок окна терминала: остановлен вызов неопределённой процедуры (30,9 с)
С ключами по умолчанию (-ThinClient -Server -ExternalConnection) прошли: ТоварыУчет.НетТакойПроцедуры(), добавление третьего параметра у ЦеныУчет.Применить при неизменённом вызывающем модуле и вызов этого метода с лишними аргументами.
25.10 я повторила все 12 сценариев на той же выгрузке с HOOK_CHECKS="-ThinClient -Server -ExternalConnection -ExtendedModulesCheck". Вызов ТоварыУчет.НетТакойПроцедуры() хук остановил, платформа вернула код 101 и сообщение «ОбщийМодуль.ЦеныУчет.Модуль Возможно ошибочный метод: "НетТакойПроцедуры"». Новый параметр у Применить и лишние аргументы прошли и с ключом: число аргументов при вызове метода другого модуля платформа не сверила. Остальные сценарии дали те же результаты, что и без ключа, полное время хука с изменёнными модулями составило 33,3-33,8 с. Как ключ работает на 15 правках «Нано-УТ 2.0» и где его дополняет скрипт, разобрано в статье про поиск вызовов удалённых процедур.
Сколько ждать
В новом прогоне из 12 попыток восемь прошли, четыре были остановлены.
| Сценарий | Коммит | Полное время хука, с | Весь git commit, с |
|---|---|---|---|
| Первый запуск версии 2 | прошёл | 44,1 | 44,6 |
| 1. Коммит без файлов конфигурации (README.md) | прошёл | 0,1 | 0,9 |
| 2. Безобидная правка: комментарий в одном модуле | прошёл | 31,3 | 31,8 |
| 3. Синтаксическая ошибка: убран «КонецЦикла» | остановлен | 32,0 | 32,7 |
| 4. Вызов несуществующей процедуры общего модуля | прошёл | 31,0 | 31,5 |
| 5. Сигнатура метода изменена в одном модуле, вызывающий модуль в коммит не входит | прошёл | 32,1 | 32,5 |
| 5а. Вызов неопределённой процедуры без имени модуля (в этом же модуле) | остановлен | 30,5 | 30,9 |
| 5б. Лишний аргумент при вызове метода другого модуля | прошёл | 30,1 | 30,5 |
| 6. Повреждённый файл метаданных (XML) | остановлен | 19,4 | 19,8 |
| 7. Правка в 15 модулях сразу | прошёл | 30,3 | 30,9 |
| 8. Обход хука: сломанный цикл с --no-verify | прошёл | не запускался | 0,2 |
| 9. После обхода: следующий обычный коммит чужого файла | остановлен | 33,4 | 33,8 |
В столбце «Полное время хука» учтены извлечение снимка, создание базы, загрузка, проверка и очистка временного каталога. «Весь git commit» включает также работу самого Git. На каждую строку приходится одна попытка; это не средние значения и не процентили.
В первом прогоне 22.10 старая версия дала 10,9 с до завершения проверки одного модуля и 11,8 с для 15 модулей. У ошибочных попыток её таймер останавливался до восстановления базы. Эти числа относятся к старому журналу и не характеризуют версию 2.
Обход хука и серверная проверка
git commit --no-verify обходит pre-commit. Ошибочный коммит появляется в истории сразу, и последующая проверка не может отменить этот факт.
В первой версии следующий коммит другого модуля прошёл: накопленная база не получила ошибку из обойдённого коммита. Версия 2 собирает полный снимок индекса заново. В повторном опыте следующий обычный коммит модуля был остановлен: платформа нашла оставленный без КонецЦикла модуль; хук занял 33,4 с, вся попытка коммита 33,8 с.
Рис. 4. Снимок окна терминала: сломанный цикл прошёл с --no-verify, следующий обычный коммит другого модуля остановлен (31,3 с)
Коммит только README.md по-прежнему пропускает платформенную проверку. Локальный хук не защищает репозиторий от сознательного обхода. Проверку на сервере следует настроить отдельно и сделать условием принятия изменений; один факт наличия CI этого не обеспечивает.
Что проверяет комплект и где его границы
verify.py проверяет обычный коммит, отказ с диагностикой, отсутствие созданного коммита после отказа, восстановление работы и --no-verify. test_regressions.py проверяет дополнительные сценарии на заглушке. В старой версии пять регрессионных проверок воспроизводили дефекты; после исправления они проходят.
Рис. 5. Снимок окна терминала: verify.py и test_regressions.py из архива, все проверки пройдены
Удаление и переименование проверены на заглушке как операции со снимком Git. Корректность изменения дерева метаданных при таких операциях на настоящей платформе отдельно не испытывалась.
Не проверены большие типовые конфигурации, расширения, rebase и сложные слияния, графические Git-клиенты, Linux/macOS и другие версии платформы. Выгрузка должна быть полной. Хук не запускает бизнес-логику и проверяет только выбранные контексты компиляции. При принудительном завершении процесса временный каталог может остаться на диске.
Сценарий run_scenarios.py рассчитан на конкретные модули исходной «Нано-УТ 2.0». Выгрузка в архив не входит; применять этот сценарий к произвольной конфигурации нельзя. Сам хук подключается к своей выгрузке по инструкции выше.
Файл к статье
В git-hook-companion-v2.zip находятся хук, README.md с подключением, сценарий опыта на платформе, заглушка, два набора проверок и журналы версий 1 и 2. Для проверки после распаковки:
Для повторного опыта с исходной «Нано-УТ» передайте run_scenarios.py путь --src, новый каталог --work и путь журнала --out. Существующий --work не удаляется и не переиспользуется.
Итог
Проверка платформой до коммита останавливает часть ошибок и сразу показывает диагностику разработчику. Приёмка первой версии выявила проблему в подготовке самой проверяемой базы. В исправленном комплекте каждый запуск получает полный снимок индекса и отдельную базу. Цена этого решения видна в новом замере. Ограничения /CheckModules и штатный обход pre-commit остаются, поэтому серверная проверка нужна независимо от локального хука.
Источники
- Git: pre-commit и другие хуки
- Git: write-tree
- Автоматизация работы Git + 1С:Конфигуратор
- Распаковка файлов обработок/отчетов при работе с GIT precommit
Вступайте в нашу телеграмм-группу Инфостарт