Автоматическая генерация лога изменений проекта с помощью GitLab
В этой небольшой статье поговорим о том, что такое лог изменений проекта, зачем он нужен и как можно автоматизировать его генерацию с помощью GitLab.
Что такое changelog и для чего он нужен?
Лог изменений проекта (changelog) — это документ, в котором обычно содержится упорядоченный список версий проекта с датами их выхода, а также перечень всех изменений для каждой из версий.
Changelog в первую очередь будет полезен самим разработчикам, с его помощью можно быстро найти в какой версии проекта была добавлена очередная фича ломающая прод или на демонстрации поможет вспомнить все изменения, сделанные за итерацию. Также будет полезен как для менеджеров, следящих за развитием продукта, так и для обычных пользователей которые хотят знать, какие изменения попали в текущую версию и нужно ли им обновлять приложение.
Как вести лог изменений?
Как минимум, хороший лог изменений должен придерживаться следующих принципов:
Для каждой версии должен быть отдельный раздел.
Группировать изменения по категориям (Feature, Bug fix, Changed и т.п).
Самые новые версии должны располагаться в начале документа.
Иметь возможность навигации по файлу.
Файл с логом можно вести вручную, но мало какой разработчик будет с энтузиазмом это делать, а если вы поддерживаете одновременно несколько версий продукта, то это превращается в очень нудное занятие. Другим вариантом будет автоматизация этого процесса.
Одним из способов генерации лога изменений (который мы и будем использовать), будет генерация лога из списка коммитов, но поскольку частенько их пишут как попало, то в первую очередь нужно, чтобы команда разработки, при написании коммитов придерживалась определенного стиля. Этот стиль будет зависеть от того, что вы хотите видеть в логе изменений, можно воспользоваться чем-то готовым или написать что-то свое.
Как генерировать?
Для генерации воспользуемся функциональностью GitLab API, с его помощью будет формироваться файл (CHANGELOG.md
) с логом изменений, основанный на заголовках коммитов. Добавляются только те коммиты, которые включают в себя определенную метку (Git trailers). GitLab использует эти метки для того, чтобы сгруппировать изменения по категориям.
Для генерации нужно выполнить POST запрос:
%gitlab-host%/api/v4/projects/%id%/repository/changelog
gitlab-host — это адрес на котором расположен сервер GitLab с вашим репозиторием.
id — это project id вашего репозитория, который можно посмотреть в настройках на вкладке «General».
Также нужно передать токен доступа для api, который можно получить в настройках на вкладке «Access Tokens». (или в настройках вашего профиля, на вкладке «Access Tokens».) И как минимум, обязательный атрибут «version» — версия, для которой генерируется лог изменений. Список всех атрибутов.
Результатом выполнения запроса, будет новый раздел в файлеCHANGELOG.md
в выбранном репозитории. По умолчанию, диапазон коммитов начинается с последнего тега, идущего до версии, указанной в атрибуте «version» и заканчивается веткой по умолчанию в проекте, в этой же ветке и обновится файл с логом изменений.
Для того, чтобы GitLab мог автоматически находить последний тег, нужно чтобы и версия, и имя тега были оформлены в соответствии с семантикой версионирования.
Если мы хотим именовать как-то по-другому или использовать другой диапазон коммитов, то на помощь приходят атрибуты:
from — название ветки, последний коммит которой станет началом диапазона. Сам коммит не будет включен в список.
to — название ветки, последний коммит которой станет концом диапазона. Сам коммит будет включен в список.
branch — название ветки, в которой будет обновлен/создан файл
CHANGELOG.md
.
Например, выполним несколько запросов с исходными данными:
Project id — 111
Gitlab-host — https://gitlab.com/
API access token — token
Имя последнего тега — 0.9.0
Имя ветки по умолчанию — main
curl --header "PRIVATE-TOKEN: token" --data "version=1.0.0" "https://gitlab.com/api/v4/projects/111/repository/changelog"
Результатом выполнения будет новый раздел в ветке main, с подзаголовком 1.0.0 и диапазоном включенных коммитов 0.9.0…main.
curl --header "PRIVATE-TOKEN: token" --data "version=1.0.0&from=release_0.9.0&to=develop&branch=develop" "https://gitlab.com/api/v4/projects/111/repository/changelog"
Результатом выполнения будет новый раздел в ветке develop, с подзаголовком 1.0.0 и диапазоном включенных коммитов release_0.9.0…develop.
Как кастомизировать?
Для кастомизации используется конфигурационный файл в формате YAML. Файл должен располагаться в корне репозитория по пути: .gitlab/changelog_config.yml
Чтобы GitLab начал распознавать файл конфигурации, он должен быть расположен в ветке по умолчанию.
Для редактирования доступны следующие переменные:
date_format — формат даты, который будет использоваться в заголовке нового раздела лога изменений
template — формат данных, который будет использоваться для отображения каждой категории лога изменений
categories — псевдоним, который будет использоваться как имя категории, вместо тех, которые мы используем, как метки коммитов (git trailers)
Для примера, структура наших коммитов будет выглядеть так:
<Тип>(номер задачи): Заголовок
— Подробное описание (если оно требуется)
[git trailers]
Используя стандартные настройки, сгенерированный файл будет выглядеть так:
## 1.0.0 (2021-08-31)
### bug (2 changes)
- [bug(#12445): Исправлено зависание приложения, при нажатии кнопки "Выход"](Nethius/example@commit-sha1)([merge request](Nethius/example!4))
- [bug(#12347): Исправлено отображение кнопок "Добавить", "Удалить"](Nethius/example@commit-sha1)
### performance (2 changes)
- [refactoring(#12349): Повышена скорость сборки приложения](Nethius/example@commit-sha1)
- [refactoring(#12348): Повышена скорость загрузки приложения](Nethius/example@commit-sha1)
### feature (2 changes)
- [feature(#12346): Добавлена поддержка файлов формата .md .yml](Nethius/example@commit-sha1)
- [feature(#12345): Реализована форма авторизации](Nethius/example@commit-sha1)
Теперь попробуем поменять заголовки категорий и добавить для каждой записи автора коммита.
В примере выше мы используем стандартный git trailer — Changelog и используемые для него значения: feature, bug, performance, которые и стали названиями категорий.
Чтобы изменить названия категорий, нужно добавить в файл конфигурации changelog_config.yml
следующие строки:
categories:
feature: Features
bug: Bug fixes
performance: Performance improvements
Для генерации данных в категориях, используются шаблоны. Для примера выше, шаблон выглядит так:
template: |
{% if categories %}
{% each categories %}
### {{ title }} ({% if single_change %}1 change{% else %}{{ count }} changes{% end %})
{% each entries %}
- [{{ title }}]({{ commit.reference }})\
{% if merge_request %} ([merge request]({{ merge_request.reference }})){% end %}
{% end %}
{% end %}
{% else %}
No changes.
{% end %}
Здесь мы в основном цикле проходим по всем категориям, отображаем название и количество записей в категории. В вложенном цикле совершаем обход всех записей и выписываем заголовок коммита и ссылку на него, если есть ссылка на МР, то добавляем её.
{% … %} — используется для условий (if/else) и циклов (each). Каждое выражение, должно закрываться с помощью {% end %}
{{ … }} — используется для отображения данных доступных в шаблоне
Для отображения автора коммита, изменим текст шаблона, добавив в вложенный цикл строку by {{ author.reference }}
после вывода ссылки на коммит.
После всех изменений, файл changelog_config.yml
будет выглядеть следующим образом:
---
categories:
feature: Features
bug: Bug fixes
performance: Performance improvements
template: |
{% if categories %}
{% each categories %}
### {{ title }} ({% if single_change %}1 change{% else %}{{ count }} changes{% end %})
{% each entries %}
- [{{ title }}]({{ commit.reference }}) by {{ author.reference }}\
{% if merge_request %} ([merge request]({{ merge_request.reference }})){% end %}
{% end %}
{% end %}
{% else %}
No changes.
{% end %}
А сгенерированный файл CHANGELOG.md
так:
## 1.0.0 (2021-08-31)
### Bug fixes (2 changes)
- [bug(#12445): Исправлено зависание приложения, при нажатии кнопки "Выход"](Nethius/example@commit-sha1) by @Nethius ([merge request](Nethius/example!4))
- [bug(#12347): Исправлено отображение кнопок "Добавить", "Удалить"](Nethius/example@commit-sha1) by @Nethius
### Performance improvements (2 changes)
- [refactoring(#12349): Повышена скорость сборки приложения](Nethius/example@commit-sha1) by @Nethius
- [refactoring(#12348): Повышена скорость загрузки приложения](Nethius/example@commit-sha1) by @Nethius
### Features (2 changes)
- [feature(#12346): Добавлена поддержка файлов формата .md .yml](Nethius/example@commit-sha1) by @Nethius
- [feature(#12345): Реализована форма авторизации](Nethius/example@commit-sha1) by @Nethius
Как автоматизировать?
Для начала настроить GitLab CI/CD. После того, как этот этап пройден, добавить в файл .gitlab-ci.yml
новый stage (или изменить уже существующий) для обновления лога изменений. В нем мы должны получить имена веток для атрибутов from и to и после этого выполнить POST запрос для генерации файла CHANGELOG.md
.
Например, пусть наша выборка коммитов начинается с последнего тега и заканчивается текущей версией релиза. Версию лога изменений, допустим, будем брать из файлов проекта, stage будет запускаться только для ветки релиз.
update-changelog:
stage: update_changelog
script:
- latestVersion=$(git describe --tags --abbrev=0)
- currentVersion=$(grep -oP '(?<=VERSION ")([^"]*)' version.h)
- |
curl --header "PRIVATE-TOKEN: token" --data "version=$currentVersion&from=$latestVersion&to=release&branch=release" "https://gitlab.com/api/v4/projects/111/repository/changelog"
only:
- release
Теперь каждый раз при сборке релиза, будет добавляться новый раздел с версией currentVersion в файл CHANGELOG.md
.
Важно, что если раздел с текущей версией уже существует, то дополняться новыми коммитами он не будет.
Итог
Мы за пару часов, настроили простую автоматическую генерацию файла с логом изменений, который даже в таком виде, будет полезен на небольших проектах, уменьшит рутину мейнтейнеров или например, поможет получать меньше обращений от тех.поддержки с вопросами в какой версии добавлена фича.
Спасибо за чтение!
Теги: GitLab CI, GitLab, Changelog, DevOps
Хабы: Git