Эпизод #5 - Overcommit
Overcommit - инструмент для удобного управления хуками гита, рассмотрим его как инструмент для самоконтроля по написанию чистого кода.
Overcommit будет полезен как фронтендерам, так и бекендерам за счет того, что имеет большую базу предустановленных хуков.
В данной статье будет рассмотрена настройка проверки кода утилитами RuboCop
и Fasterer
при каждой попытке сделать коммит.
Установка
Overcommit устанавливается как gem, командой:
gem install overcommit
Теперь можно устанановить хуки в репозиторий.
Важно: установка производится в корневом каталоге проекта, где инициализирован Git репозиторий. Если репозиторий не инициализирован, то запустите команду git init
.
overcommit --install
Данная команда заменит все существующие хуки. Ваши хуки будут сохранены в резервной копии и их можно восстановить командой:
overcommit --uninstall
Конфигурация
Все специфичные для репозитория настройки хранятся в файле .overcommit.yml
, который распологается в корневой директории вашего проекта.
Ваш конфигурационный файл будет автоматически расширять настройки по умолчанию.
Предположим, что мы хотим настроть хуки, которые будут срабатывать каждый раз, когда мы создаем новый коммит (PreCommit
).
Хуки должны проверить код на соответствие так называемым style-guide и убедиться, что при написании кода мы использовали самые оптимальные методы.
В этом нам помогут уже знакомые по предыдущим эпизодам инструменты Rubocop и Fasterer.
Все возможные PreCommit-хуки можно найти тут.
Начнем с подключения Rubocop.
.overcommit.yml
Precommit:
RuboCop:
enabled: true
- Указываем момент срабатывания хука -
PreCommit
. - Прописываем название самого хука -
Rubocop
. - Активируем его
enabled: true
Далее нужно определиться с поведением хука для строк, которые не были модифицированны. Ранее мы определились, что мы хотим, чтобы хук анализировал только тот код, который был изменен. Поэтому нужно добавить опцию problem_on_unmodified_line
с флагом ignore
. А также определить поведение, когда будут найдены несоответствия. Настроим так, чтобы коммит нельзя было создать, пока не будут исправлены все несоответствия. В этой задаче нам поможет флаг on_warn
с флагом fail
.
Precommit:
RuboCop:
enabled: true
on_warn: fail
problem_on_unmodified_line: ignore
Часто требуется исключить некоторые файлы из проекта. Допустим, мы работаем над Rails проектом и хотим исключить из хука Rubocop
все файлы, которые лежат в директории **/db/
. Тогда наш конфигурационный файл примет следующий вид:
Precommit:
RuboCop:
enabled: true
on_warn: fail
problem_on_unmodified_line: ignore
exclude:
- '**/db/'
Теперь можно проделать тоже самое для хука Fasterer
. Все шаги практически идентичны предыдущим, за несколькими исключениями. Вот так будет выглядеть обновленный конфигурационный файл:
Precommit:
RuboCop:
enabled: true
on_warn: fail
problem_on_unmodified_line: ignore
exclude:
- '**/db/'
Fasterer:
enabled: true
on_warn: fail
problem_on_unmodified_line: ignore
Важно: убедитесь, что у вас установлены Rubocop
и Fasterer
, перед использованием этого конфигурационного файла.
gem install fasterer rubocop
После того как конфигурационный файл подготовлен необходимо прописать новые хуки в настройки вашего репозитория:
overcommit --sign
Данную команду нужно запускать каждый раз, после того как вы внесли какие-либо изменения в конфигурационный файл.
Использование
После того как Overcommit настроен и хуки прописаны в вашем репозитории, при попытке сделать коммит, будет производиться анализ измененного кода. Если будут найдены какие-либо несоответствия прописанным правилам, созадние коммита будет прервано и указаны инструкции для испавления ошибок.
Для примера напишем класс User
.
Добавим пару простых методов, первый будет находить первого администратора среди всех пользователей, второй будет возвращать название роли пользователя.
class User
attr_reader :first_name, :last_name, :email, :admin?
def self.first_admin
all.select { |user| user.admin? }.first
end
def role_name
if admin?
"Администратор"
else
"Пользователь"
end
end
end
Добавим новый код репозиторий:
git add user.rb
git commit
Добавленный код был проанализирован, коммит отменен и мы видим допущенные ошибки.
Внесем изменения согласно данному отчету:
class User
attr_reader :first_name, :last_name, :email, :admin?
def self.first_admin
all.detect(:admin?)
end
def role_name
if admin?
'Администратор'
else
'Пользователь'
end
end
end
Повторим создание коммита:
git add user.rb
git commit
Теперь код валиден и мы можем завершить создание коммита
Бывают случаи, когда исправить код не получается, а коммит нужно сделать и причем срочно. Для таких случаем нам придут на помощь переменные окружения. С помощью них можно отключить определенный хук или наоборот запустить только конкретный, а можем поностью провести коммит отключив все хуки. Вот примеры таких команд:
SKIP=RuboCop git commit # пропустить хук RuboCop
ONLY=RuboCop git commit # запустить только RuboCop
OVERCOMMIT_DISABLE=1 git commit # отключить все хуки
Для удобства можно создать алиасы для часто используемых команд.
Обязательно загляните в оф. репозиторий и изучите все возможности Overcommit.
В этой статье рассмотрена лишь малая часть возможностей этой замечательной утилиты, но даже эта малая часть поможет сделать вашу работу чуточку проще.