Back

Автоматизация проверки кода с помощью Git pre-commit hooks

Автоматизация проверки кода с помощью Git pre-commit hooks

Каждый разработчик знает, как неприятно отправить код в репозиторий и увидеть, что CI/CD pipeline упал из-за проблем с форматированием или ошибок линтера. А что если можно было бы выявлять эти проблемы еще до того, как они попадут в ваш репозиторий? Git pre-commit hooks предлагают мощное решение, которое запускает автоматические проверки локально, экономя время и поддерживая единообразное качество кода в команде.

В этой статье мы рассмотрим настройку git pre-commit hooks с использованием фреймворка pre-commit, конфигурацию основных инструментов, таких как ESLint, Prettier и Black, а также внедрение лучших практик, которые сделают ваш рабочий процесс разработки гладким и эффективным.

Ключевые выводы

  • Git pre-commit hooks выполняют автоматические проверки перед коммитами, предотвращая попадание типичных проблем в репозиторий
  • Фреймворк pre-commit упрощает управление hooks с помощью YAML-конфигурации и поддержки различных языков программирования
  • Оптимизация скорости и постепенное внедрение критически важны для принятия командой
  • Альтернативные инструменты, такие как Husky и Lefthook, предлагают различные подходы для специфических потребностей

Что такое Git Pre-Commit Hooks?

Git hooks — это скрипты, которые Git выполняет до или после таких событий, как commit, push и receive. Git pre-commit hook запускается после того, как вы добавили изменения в staging area, но до того, как Git создаст коммит. Если hook завершается с ненулевым статусом, Git отменяет коммит, давая вам возможность сначала исправить проблемы.

Хотя вы можете писать hooks как простые shell-скрипты в .git/hooks/, управление ими становится сложным по мере роста проекта. Здесь блестяще проявляет себя фреймворк pre-commit — он предоставляет стандартизированный способ управления и совместного использования hooks в команде.

Зачем использовать фреймворк Pre-Commit?

Фреймворк pre-commit решает несколько болевых точек нативных Git hooks:

  • Простая установка и обновления: Hooks версионируются и устанавливаются через простую YAML-конфигурацию
  • Независимость от языка: Запуск Python-линтеров, JavaScript-форматеров и shell-скриптов из одной конфигурации
  • Селективное выполнение: Hooks запускаются только для измененных файлов, сохраняя быстроту коммитов
  • Единообразие в команде: Совместное использование одного файла .pre-commit-config.yaml во всей команде

Настройка Pre-Commit в вашем проекте

Сначала установите пакет pre-commit:

pip install pre-commit

Создайте файл .pre-commit-config.yaml в корне проекта. Вот практичная конфигурация, которая покрывает основные потребности:

repos:
  # Basic file fixes
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.5.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-yaml
      - id: check-added-large-files

  # Python formatting with Black
  - repo: https://github.com/psf/black
    rev: 24.2.0
    hooks:
      - id: black
        files: \.py$

  # Python type checking with Mypy
  - repo: https://github.com/pre-commit/mirrors-mypy
    rev: v1.8.0
    hooks:
      - id: mypy
        additional_dependencies: [types-all]
        files: \.py$

  # JavaScript/TypeScript with Prettier
  - repo: https://github.com/pre-commit/mirrors-prettier
    rev: v3.1.0
    hooks:
      - id: prettier
        files: \.(js|jsx|ts|tsx|json|css|md)$

  # JavaScript/TypeScript linting with ESLint
  - repo: https://github.com/pre-commit/mirrors-eslint
    rev: v8.56.0
    hooks:
      - id: eslint
        files: \.(js|jsx|ts|tsx)$
        additional_dependencies:
          - eslint-config-standard
          - eslint-plugin-react

  # Run project tests
  - repo: local
    hooks:
      - id: pytest
        name: pytest
        entry: pytest
        language: system
        pass_filenames: false
        always_run: true

Установите git hooks:

pre-commit install

Теперь ваши hooks будут запускаться автоматически при каждом коммите. Чтобы запустить их вручную на всех файлах:

pre-commit run --all-files

Оптимизация производительности hooks

Скорость имеет значение — медленные hooks отбивают у разработчиков желание часто коммитить. Следуйте этим практикам:

Запускайте hooks только для staged-файлов: Фреймворк pre-commit делает это по умолчанию, но убедитесь, что ваши кастомные hooks соблюдают этот паттерн.

Используйте быстрые инструменты: Выбирайте Ruff вместо Flake8 для Python или Biome вместо ESLint для JavaScript, когда скорость критична.

Пропускайте дорогие проверки локально: Оставляйте комплексные наборы тестов для CI/CD. Локальные hooks должны фокусироваться на быстрых победах, таких как форматирование и базовый линтинг.

Используйте параллелизм, когда возможно: Некоторые инструменты поддерживают параллельное выполнение. Например, pytest может запускать тесты параллельно с pytest-xdist.

Лучшие практики внедрения в команде

Внедрение pre-commit hooks в команде требует продуманного подхода:

Начинайте с малого: Начните с неинтрузивных hooks, таких как удаление trailing whitespace. Добавляйте более строгие проверки постепенно.

Документируйте настройку: Включите инструкции по установке в ваш README. Сделайте это частью процесса онбординга.

Учитывайте различия в окружениях: Используйте language-agnostic hooks, где это возможно. Для специфичных инструментов убедитесь, что ваш .pre-commit-config.yaml указывает совместимые версии.

Предоставьте пути отступления: Иногда разработчикам нужно обойти hooks. Флаг --no-verify пропускает все hooks:

git commit --no-verify -m "Emergency fix"

Используйте это экономно и документируйте, когда это уместно.

Альтернативные подходы

Хотя pre-commit — самый популярный фреймворк, существуют альтернативы:

Husky: Популярен в JavaScript-проектах, хорошо интегрируется с npm-скриптами.

Нативные Git hooks: Прямые shell-скрипты в .git/hooks/ предлагают максимальный контроль, но лишены портабельности.

Lefthook: Быстрая кроссплатформенная альтернатива с поддержкой параллельного выполнения.

Для большинства команд pre-commit предлагает лучший баланс функций, производительности и поддержки экосистемы.

Распространенные ошибки и решения

Сбои hooks в CI: Убедитесь, что CI-окружения имеют все необходимые зависимости. Рассмотрите запуск pre-commit run --all-files как шага CI.

Проблемы, специфичные для платформы: Тестируйте hooks на всех платформах, которые использует ваша команда. При необходимости используйте Docker для согласованных окружений.

Конфликты слияния в конфигурационных файлах: Делайте изменения в .pre-commit-config.yaml минимальными и атомарными. Обновляйте версии hooks в отдельных коммитах.

Заключение

Git pre-commit hooks превращают контроль качества кода из реактивного процесса в проактивный. Выявляя проблемы до их попадания в репозиторий, вы экономите время, сокращаете переключения контекста и поддерживаете более высокие стандарты во всей кодовой базе. Начните с базовых hooks форматирования, постепенно добавляйте линтеры и проверки типов, и всегда приоритизируйте скорость, чтобы рабочий процесс команды оставался гладким.

Ключ к успешному внедрению лежит в балансе между тщательностью и пользовательским опытом разработчика. Быстрые, сфокусированные hooks, которые предоставляют немедленную ценность, станут неотъемлемой частью рабочего процесса вашей команды.

Часто задаваемые вопросы

Да, pre-commit отлично работает с монорепозиториями. Вы можете настроить различные hooks для разных паттернов файлов и директорий. Используйте ключи files и exclude в вашей конфигурации для таргетирования конкретных языков или папок внутри репозитория.

Используйте менеджеры версий языков, такие как nvm или pyenv, вместе с pre-commit. Альтернативно, укажите language_version в конфигурации вашего hook или используйте Docker-based hooks для обеспечения согласованных окружений на всех машинах разработчиков.

Без установленного pre-commit hooks не будут запускаться локально, но ваш код все равно будет закоммичен. Для обеспечения стандартов запускайте проверки pre-commit в вашем CI pipeline как страховочную сеть и сделайте установку pre-commit частью документации по настройке проекта.

Gain control over your UX

See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay. — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay