12k
All articles

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

Настройка Git pre-commit hooks через фреймворк pre-commit, ESLint, Prettier и Black помогает выявлять ошибки форматирования и линтинга перед каждым коммитом.

OpenReplay Team
OpenReplay Team
Автоматизация проверки кода с помощью 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 с монорепозиториями, содержащими несколько языков программирования?

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

Как обрабатывать hooks, которые требуют специфичных версий Node или Python?

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

Что происходит, если у разработчика не установлен pre-commit?

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

Open-source session replay

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.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.