В этой небольшой статье поговорим о том, что такое лог изменений проекта, зачем он нужен и как можно автоматизировать его генерацию с помощью GitLab.
Changelog в первую очередь будет полезен самим разработчикам, с его помощью можно быстро найти в какой версии проекта была добавлена очередная фича ломающая прод или на демонстрации поможет вспомнить все изменения, сделанные за итерацию. Также будет полезен как для менеджеров, следящих за развитием продукта, так и для обычных пользователей которые хотят знать, какие изменения попали в текущую версию и нужно ли им обновлять приложение.
Одним из способов генерации лога изменений (который мы и будем использовать), будет генерация лога из списка коммитов, но поскольку частенько их пишут как попало, то в первую очередь нужно, чтобы команда разработки, при написании коммитов придерживалась определенного стиля. Этот стиль будет зависеть от того, что вы хотите видеть в логе изменений, можно воспользоваться чем-то готовым или написать что-то свое.
Для генерации нужно выполнить POST запрос:
%gitlab-host%/api/v4/projects/%id%/repository/changelog
Результатом выполнения запроса, будет новый раздел в файлеCHANGELOG.md в выбранном репозитории. По умолчанию, диапазон коммитов начинается с последнего тега, идущего до версии, указанной в атрибуте "version" и заканчивается веткой по умолчанию в проекте, в этой же ветке и обновится файл с логом изменений.
Для того, чтобы GitLab мог автоматически находить последний тег, нужно чтобы и версия, и имя тега были оформлены в соответствии с семантикой версионирования.
Если мы хотим именовать как-то по-другому или использовать другой диапазон коммитов, то на помощь приходят атрибуты:
Результатом выполнения будет новый раздел в ветке 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.
<Тип>(номер задачи): Заголовок
- Подробное описание (если оно требуется)
[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 %}
Здесь мы в основном цикле проходим по всем категориям, отображаем название и количество записей в категории. В вложенном цикле совершаем обход всех записей и выписываем заголовок коммита и ссылку на него, если есть ссылка на МР, то добавляем её.
После всех изменений, файл 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
Например, пусть наша выборка коммитов начинается с последнего тега и заканчивается текущей версией релиза. Версию лога изменений, допустим, будем брать из файлов проекта, 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.
Что такое 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".
Результатом выполнения запроса, будет новый раздел в файле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
Результатом выполнения будет новый раздел в ветке 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 %}
- {{ ... }} - используется для отображения данных доступных в шаблоне
После всех изменений, файл 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
В этой небольшой статье поговорим о том, что такое лог изменений проекта, зачем он нужен и как можно автоматизировать его генерацию с помощью GitLab. Что такое changelog и для чего он нужен? Лог...
habr.com