Как расширить возможности вашего проекта Java Maven с помощью Git Hooks для автоматического форматирования кода и семантического управления версиями

Вы когда-нибудь натыкались на беспорядочную кодовую базу, в которой отсутствовали некоторые основные принципы чистого кода? (Здесь краткие сведения о чистом коде) Я уже имел удовольствие видеть кодовую базу, стиль которой был перемешан с различными стилями форматирования IntelliJ. Кроме того, сообщения коммитов также были перепутаны, что затрудняло понимание прошлых изменений. Я всегда стараюсь вести линейную историю git, хотя это не всегда возможно. На мой взгляд, обычные коммиты хорошо подходят для хранения истории коммитов git, которая понятна, и, кроме того, вы можете автоматизировать создание журнала изменений и семантическое управление версиями, например, указав критические изменения в своем сообщении коммита.

Чтобы преодолеть это, я искал простое решение, которое проверяет форматирование кода и сообщение фиксации. (Серверные хуки не подходили для этих проектов, но Github Actions хорошо подходят, если они подходят). Вот почему я остановился на git-хуках.

Git-хуки — это скрипты, которые запускаются автоматически каждый раз, когда в репозитории Git происходит определенное событие. Они позволяют настраивать внутреннее поведение Git и запускать настраиваемые действия в ключевые моменты жизненного цикла разработки.

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

Итак, если вы хотите продолжить, убедитесь, что у вас есть:

  • Ява 17
  • Мавен
  • Узел

В вашем файле pom.xml в корневом каталоге вы должны настроить плагины. Этот отвечает за копирование ваших хуков в папку git hooks по умолчанию и имеет цель установить maven (здесь maven строит дерево зависимостей на основе нашего pom.xml и извлекает все необходимые компоненты, иначе мы не смогли бы собрать наш проект). Мы указали специальный хук для commit-msg и pre-commit. Вы также можете изменить весь каталог хуков по умолчанию в этой конфигурации. Позже я покажу вам, где находится папка hooks и как выглядит код.

<plugin>
    <groupId>com.rudikershaw.gitbuildhook</groupId>
    <artifactId>git-build-hook-maven-plugin</artifactId>
    <version>3.1.0</version>
    <configuration>
        <installHooks>
            <commit-msg>hooks/commit-msg</commit-msg>
            <pre-commit>hooks/pre-commit</pre-commit>
        </installHooks>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>install</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Дополнительные параметры см.: https://github.com/rudikershaw/git-build-hook

Этот плагин отвечает за форматирование вашего кода. Я использовал красивее, но вы также можете использовать формат google-java, eclipse jdt или формат palantir-java. У вас есть несколько вариантов форматирования, см. безупречный maven. Вы также можете допустить сбой ваших сборок, если форматирование неверно.

<plugin>
    <groupId>com.diffplug.spotless</groupId>
    <artifactId>spotless-maven-plugin</artifactId>
    <version>2.25.0</version>
    <configuration>
        <formats>
            <!-- prettier with java-plugin -->
            <format>
                <includes>
                    <include>src/*/java/**/*.java</include>
                </includes>

                <prettier>
                    <devDependencies>
                        <prettier>2.0.5</prettier>
                        <prettier-plugin-java>0.8.0</prettier-plugin-java>
                    </devDependencies>
                    <config>
                        <tabWidth>4</tabWidth>
                        <parser>java</parser>
                    </config>
                </prettier>
            </format>
        </formats>
    </configuration>
    <executions>
        <execution>
            <phase>verify</phase>
            <goals>
                <goal>check</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Итак, на следующем рисунке показана наша простая структура каталогов и то, где мы управляем нашими хуками. Плюсом является то, что хуки также версионируются git, если вы делаете это таким образом (если вы хотите использовать его в нескольких проектах, вы можете создать библиотеку maven для своих хуков и интегрировать их в git-build-hook- maven-плагин):

Также обязательно выполните:

  • chmod +x hooks/pre-commit
  • chmod +x hooks/commit-msg

Поскольку используемый плагин maven git-build-hook-maven-plugin копирует их в каталог git по умолчанию, и если у них нет разрешения на выполнение, мы не можем запускать наши хуки.

По сути, хук commit-msg проверяет, начинается ли сообщение с одного из разрешенных слов, и завершает работу с ошибкой, если это не так. Весь скрипт был скопирован отсюда, где автор написал хорошую статью на эту тему, но без автоматического включения, т.к. хук был вручную скопирован в директорию hooks.

#!/usr/bin/env bash

# Create a regex for a conventional commit.
convetional_commit_regex="^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\([a-z \-]+\))?!?: .+$"

# Get the commit message (the parameter we're given is just the path to the
# temporary file which holds the message).
commit_message=$(cat "$1")

# Check the message, if we match, all good baby.
if [[ "$commit_message" =~ $convetional_commit_regex ]]; then
   echo -e "\e[32mCommit message meets Conventional Commit standards...\e[0m"
   exit 0
fi

# Uh-oh, this is not a conventional commit, show an example and link to the spec.
echo -e "\e[31mThe commit message does not meet the Conventional Commit standard\e[0m"
echo "An example of a valid message is: "
echo "  feat(login): add the 'remember me' button"
echo "More details at: https://www.conventionalcommits.org/en/v1.0.0/#summary"
exit 1

Хук pre-commit выглядит следующим образом и просто применяет стиль кода:

#!/usr/bin/env bash
mvn spotless:apply

Теперь мы почти настроены, но часть, связанная с выпуском новых версий и автоматическим обновлением версий, все еще отсутствует. Автор сценария commit-msg также выпустил пакет npm, который помогает с автоматическим управлением версиями и новыми выпусками. Сначала нужно запустить

npx dwmkerr/standard-version --first-release --packageFiles pom.xml --bumpFiles pom.xml

И для каждого нового выпуска после этого просто опускайте опцию первого выпуска в команде. Запустив

git push --follow-tags

Вы отправляете вновь созданный тег в свой репозиторий вместе с журналом изменений и обновленным номером версии.

Вы можете посмотреть мой репозиторий с примерами на Github.