Как писать хорошие сообщения коммитов: Commitlint

Мы часто спешим закоммитить свои изменения в Git и в спешке пишем сообщения коммитов довольно рандомным образом. Я видел, что люди вставляют туда дату и время или даже пишут что-то типа commit 1, commit 2.

Это нехорошо. Сообщения коммитов должны быть полезными. В них должна быть смысловая нагрузка, чтобы люди, работающие над проектом и читающие код, могли прочесть сообщение и узнать, какие изменения были внесены тем или иным коммитом.

Давайте разберем простой способ решения этой проблемы.

Что такое Commitlint?

Commitlint — это простой инструмент для линтинга сообщений коммитов. Он следит за тем, чтобы ваши сообщения соответствовали установленному набору правил.

Commitlint запускается как husky pre-commit hook, то есть до коммита кода, и блокирует коммит в случае, если сообщение не проходит проверку.

Использование Commitlint в простом JavaScript-проекте

Давайте рассмотрим на примере, как настроить Commitlint в простом JavaScript-проекте. Для начала мы создадим пустой проект:

mkdir commitlint_example && cd commitlint_example

npm init
# OR
yarn init
# Just accept the defaults when prompted to configure the project

Теперь давайте инициализируем пустой Git-репозиторий:

git init

Мы также должны добавить файл .gitignore, чтобы некоторые файлы не входили в коммиты:

node_modules/

От редакции Techrocks. Рекомендуем статью «Как удалить конфиденциальный файл из истории коммитов на GitHub».

После этого добавляем файл index.js и выводим что-нибудь в консоль:

console.log("Hello, World!!!")

При запуске node . в вашем терминале должен выводиться текст:

Настройка Commitlint

Мы настроим Commitlint, следуя официальной документации по локальной настройке.

Для начала нам нужно установить CLI Commitlint (интерфейс командной строки) и добавить конфиг (в данном случае — конфиг дефолтного Соглашения о коммитах).

npm install @commitlint/cli @commitlint/config-conventional --save-dev
# OR
yarn add -D @commitlint/cli @commitlint/config-conventional

Добавим кое-какие настройки конфигурации в файле commitlint.config.js:

module.exports = {
    extends: [
        "@commitlint/config-conventional"
    ],
}

Теперь следует установить husky, чтобы запускать Commitlint как pre-commit hook.

npm install husky --save-dev
# OR
yarn add -D husky

Еще надо включить хуки husky:

npx husky install
# OR
yarn husky install

Мы можем добавить шаг prepare, чтобы включить хуки при установке:

npm set-script prepare "husky install"

С установкой husky покончено. Теперь нужно добавить pre-commit hook для запуска Commitlint перед коммитом кода.

npx husky add .husky/commit-msg "npx --no -- commitlint --edit $1"
# OR
yarn husky add .husky/commit-msg "yarn commitlint --edit $1"

Настройка Commitlint завершена. Давайте проверим, все ли работает.

Для начала добавим все файлы в стейджинг:

git add -A

Теперь попробуем сделать коммит изменений. При этом напишем сообщение коммита, не придерживаясь установленных правил:

git commit -m "set up a basic js project, added commitlint and husky for liniting commit messages"

Вы должны получить примерно такой результат (с ошибками). Если коммит пройдет успешно, скорее всего, вы где-то ошиблись в настройках. Проверьте, все ли указанные команды вы запустили и попробуйте отменить коммит, запустить скрипты и закоммитить изменения снова.

А теперь давайте сделаем коммит с правильным сообщением. Запустите следующую команду:

git commit -m "ci: initialised basic js project, added commitlint and husky to lint commit messages"

Теперь все прошло успешно.

Как работает дефолтное соглашение Commitlint

В качестве соглашения по умолчанию Commitlint использует Соглашение о коммитах. В соответствии с этим Соглашением, сообщения коммитов должны иметь следующую структуру:

<тип>[необязательный контекст]: <описание>
[необязательное тело]
[необязательная(ые) сноска(и)]

Например, если я исправил баг, имеющий отношение к UI, сообщение коммита может быть таким:

fix(ui): Button was not showing up properly on mobile view.

Здесь тип — это fix, т. е. исправление бага. В контексте указан скоуп — ui, поскольку исправление касается пользовательского интерфейса. В описании дается больше контекста относительно того, что именно исправлено.

Обратите внимание, что в контексте можно добавить не один скоуп. Например:

feat(ui,lang): added an option to save the image as svg and added language support for Spanish.

Здесь мы представили две фичи — новую кнопку для сохранения изображения в формате svg и поддержку испанского языка. Скоупы можно разделять тремя видами разделителей: запятыми, слэшами и обратными слэшами (, / \).

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

Серьезные изменения обычно обозначаются восклицательным знаком. Но вы также можете прямо написать BREAKING CHANGE в футере сообщения коммита. Хороший подход — и восклицательный знак ставить, и BREAKING CHANGE писать. Например:

refactor(runtime)!: Dropped support for NodeJS v12

BREAKING CHANGE: Support for NodeJS v12 has been dropped due to the latest refactor, please upgrade to the latest LTS version of No

Это подводит нас к многострочным сообщениям коммитов. Порой нам нужно дать больше контекста читателю, чтобы он сразу понял, что поменялось. В таком случае лучше всего включить нужную информацию в сообщение коммита. Например:

docs: Added an aria-label in the IconButton example
aria-label is a required prop by the IconButton component. If it is not present, the build will fail

Преимущества использования Commitlint

  • Автоматические логи изменений. Если коммиты соответствуют стандартному соглашению, инструменты вроде standard-version могут генерировать логи изменений автоматически. (От редакции Techrocks: см. «Что такое changelog проекта и как его создать»).
  • Более понятные коммиты. Если в сообщении указан тип коммита и скоуп, читателю проще понять, что за изменения внесены этим коммитом.
  • Соблюдение определенных правил. Когда у вас крупный проект, над которым работает много людей, трудно уследить за тем, чтобы все придерживались принятого соглашения и писали сообщения коммитов в одном стиле. Commitlint блокирует коммиты с сообщениями, не соответствующими правилам, и таким образом принудительно внедряет единообразие.

Итак, вы познакомились с основами использования Commitlint. Во второй части этой статьи мы погрузимся немного глубже и узнаем, как писать собственные правила и как запускать Commitlint CI в GitHub Actions.

Как создавать пользовательские правила Commitlint

Соглашение о коммитах подходит для большинства проектов. Но вы можете захотеть добавить какие-то правила, специфичные для вашего проекта.

Полную информацию на этот счет можно найти в документации.

Для примера мы возьмем приложение, в котором есть библиотека кнопок, созданная при помощи TailwindCSS. Вы можете добавить свое творение в это приложение при помощи пул-реквеста.

Коммиты здесь могут быть разных типов. Для примера мы возьмем тип button. Для этого мне потребуется перезаписать правило type-enum в Соглашении о коммитах.

Для этого я создам объект rules в моем конфиге Commitlint и внесу button как тип. Вот как должен выглядеть наш commitlint.config.js:

module.exports = {
    extends: [
        "@commitlint/config-conventional"
    ],
    rules: {
        "type-enum": [2, "always", ["build", "chore", "ci", "docs", "feat", "fix", "perf", "refactor", "revert", "style", "test", "button"]],
    }
}

Я просто добавил тип button поверх типов, установленных по умолчанию.

Давайте это закоммитим:

git add -A
git commit -m "ci(commitlint): added button as a type of commit"

Теперь протестируем наш тип button. Для примера я просто добавлю новую строку в файл index.js. Теперь он будет выглядеть так:

console.log("Hello, World!!!")
console.log("New Button")

Давайте сделаем коммит:

git add -A
git commit -m "button: added a new console.log to qualify as a button"

У вас должен получиться примерно такой же результат.

Как использовать Commitlint с GitHub Actions

Линтинг сообщений коммитов происходит локально. К сожалению, подобные проверки могут быть пропущены. Поэтому мы можем добавить еще один шаг в наш процесс CI/CD для повторной проверки.

В этом примере мы будем использовать GitHub Actions, но в документации есть официальные руководства также для Travis CI, Circle CI и GitLab CI.

Как запушить наш код на GitHub

Чтобы использовать GitHub Actions, нам сначала нужно сделать push нашего кода на GitHub. Давайте сделаем это по-быстрому.

Я воспользуюсь GitHub CLI, но вы можете делать через GUI. Главное — не забудьте добавить upstream в репозиторий.

Мы можем запушить код, запустив git push origin master.

Как настроить Workflow

Для этого примера мы используем готовый GitHub Action, найти его можно здесь: https://github.com/wagoid/commitlint-github-action.

Нам нужно создать новую папку .github, а в ней — папку workflows. Затем мы создаем файл commitlint.yml и добавляем конфигурацию workflow.

.github/workflows/commitlint.yml:

name: Lint Commit Messages
on: [pull_request, push]

jobs:
  commitlint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0
      - uses: wagoid/commitlint-github-action@v4

Этот workflow будет запускаться при каждом пуше кода на GitHub и при каждом открытии пул-реквеста. Чтобы протестировать, сделаем коммит и пуш нашего кода.

git add -A
git commit -m "ci(commitlint,workflow): added GitHub action workflow to run commitlint on push and pr"
git push origin master

Теперь мы можем переместиться в GitHub-репозиторий, во вкладку actions, и там увидим наш workflow.

Я сделал опечатку в имени папки workflows, так что мне пришлось внести исправление и заново сделать коммит и пуш, так что имя коммита отличается.

Просматривая подробности, вы можете видеть, что workflow был успешен, поскольку все коммиты пока соответствовали соглашению.

Мы можем также посмотреть логи:

Теперь, когда вы настроили Commitlint, будет хорошей идеей добавить автоматизированные логи изменений. Зайдите в репозиторий standard version и попытайтесь реализовать это самостоятельно!

Перевод статьи «How to Write Good Commit Messages with Commitlint».

[customscript]techrocks_custom_after_post_html[/customscript]

[customscript]techrocks_custom_script[/customscript]

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Прокрутить вверх