Changelog как писать
Перейти к содержимому

Changelog как писать

CHANGELOG.md: ручное и автоматическое ведение истории изменений проекта в Git

С начала января я веду свой проектик, на котором обкатываю новые для меня технологии:

  • Статический анализ кода, phpcs, phpmd, Scrutinizer
  • Автоматическая сборка, Travis CI
  • Unit тесты, PHPUnit
  • Покрытие кода, Coveralls
  • Работу через задачи для любых изменений, Github Issues, PhpStorm tasks
  • Документирование всего: README, CHANGELOG, сайт проекта, –help

В этом посте изложена история изменений моего мнения о разных генераторах историй изменения.

Tl;dr: conventional-changelog, стандартизация коммитов.

changelog

CHANGELOG.md

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

  • Issues проекта, ветка в менеджере задач, доска проекта и т.п.
  • git log проекта

Файл CHANGELOG.md в корне проекта стал стандартом де-факто для проектов, в котором ведется история изменений, Gitlab даже делает для него отдельную вкладку на странице репозитория.

Про это, конечно, есть сайт, репозиторий на Github с тысячей звезд, проблема явно беспокоит людей.

Про ведение CHANGELOG я задумался, когда изучал проект otto, когда писал про него статью на хабр.

Структура у CHANGELOG более-менее у всех одна и та же:
  • Версия и дата релиза
  • Сломанные обратные совместимости
  • Новые фичи
  • Прочие изменения и улучшения
  • Исправленные баги

Вести такой документ достаточно просто, я за 120 коммитов почти не забывал это делать. В файле нужно всегда держать вверху секцию Next Release с подготовленными заголовками, как-то так:

Перед коммитом я всегда просматриваю дифф, в это время я записываю в коммент к коммиту кратко изменение в первую строку и более подробно в третью, если изменений больше одного, делаю в виде списка. Если про это есть задача, нужно упомянуть ее в виде #123 ссылки, Github умный и такие ссылки делает активными.

Так вот, нужно просто добавить в этот процесс копипасту коммента к коммиту в CHANGELOG, с раскладыванием по категориям изменений.

Во время релиза называем секцию, ставим ей дату, копипастим заголовки.

Процедура очень простая, настолько простая, что хочется ее поручить роботу.

github_changelog_generator

github_changelog_generator — ruby утилита, которая умеет генерировать CHANGELOG.md из любого репозитория. На выходе получаем документ типа этого, наполненный ссылками на задачи и пулл-реквесты, разбитый по категориям, все круто, как в рекламе. У меня получилось совсем не так красиво.

Что мне не понравилось в этом генераторе:

  • Текст коммитов никак не учитывает, как и текст задач.
  • Чтобы она нормально работала, нужно по полной использовать Github Issues и метки для них, пулл-реквесты, в общем сильно завязано на Github (кто бы мог подумать?), иначе будут генериться просто ссылки на диффы между тегами.
  • Нельзя указывать свои секции (например, Breaking changes встроенного нет), но есть issue #316 про это, судя по активности проекта, они скоро появятся.
  • Поведение из коробки что-то генерирует, даже если вы не думали про CHANGELOG.md до этого и не использовали Github фишки, это лучше, чем ничего. Но не намного.
  • Можно привязывать свои метки к существующим секциям лога.
  • Можно настраивать как параметрами к команде, так и конфигом. При запуске скрипт говорит: Performing task with options , так вот, каждую строку из перечисленного ниже конфига можно вставить в файл .github_changelog_generator и переопределить, заменив _ на — .
  • Поддерживает сосуществование заполняемой вручную версии (которая все равно лучше автоматической) и генерируемого лога, для этого нужно переложить старый CHANGELOG.md в HISTORY.md (или другой файл, указав его в конфиге).

В общем, github_changelog_generator в моем случае подходит хорошо, если вся работа ведется на Github, это самый простой способ получить красивый CHANGELOG.md

Но на этом я не успокоился, основная причина в том, что на рабочие проекты на Github я не делаю. Хотелось более общего решения.

git-extras changelog

tj/git-extras — это огромный (около 50) пакет дополнительных команд, упрощающих работу с git. Я его раньше уже видел, но в то время подумал, что мне и встроенных в git команд слишком много. Но в поисках генератора снова набрел на него, у него есть такая команда.

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

Для пробы сделал лог для site-setup, server-scripts, drupal-scripts, на этом успокоился, больше в общем и тестить не на чем.

Ниже я отказался от него в пользу conventional changelog .

Плюсы:
  • Простой как дверь, выполняешь команду, получаешь список изменений, разделенных версиями
Минусы:
  • Нет почти никаких настроек

rafinskipg/git-changelog

rafinskipg/git-changelog — node.js cкрипт, который парсит коммиты, написанные по стандартам Angular. Я их прочитал, оказалось, что стандарты годные, к angular никак не привязаны.

Конфликтует с git-extras, так как оба они хотят называться git-changelog. Этот я сделал симлинком git-changelog-angular .

Параметров у скрипта немного, я с ними поигрался, но ничего хорошего у меня с этим тулом не вышло. Идем дальше.

conventional-changelog

stevemao/conventional-changelog-cli — node.js скрипт, также нацелен на стандарты Angular, но, по заявлениям авторов это как раз то, что нужно:

  • поддерживает свои форматы коммитов и несколько общих: ‘angular’, ‘atom’, ‘codemirror’, ‘ember’, ‘eslint’, ‘express’, ‘jquery’, ‘jscs’, ‘jshint’
  • поддерживает шаблоны
  • протестирован, в отличие от github_changelog_generator
  • отвязан от Github
  • имеет модульную структуру и несколько модулей вокруг себя

Воспользовавшись conventional-commits-detector , узнал, что мои комменты к коммитам больше всего похожи на стандарт eslint .

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

Зато запуск без указания пресета сообщений выдал почти то же, что и git-extras , но вдобавок к этому задал мажорным и минорным версиям разный уровень и указал ссылку на коммит на Github для каждого коммита.

Сгенерировать лог с нуля можно командой:

После этого я конечно побежал исправлять логи у проектов, которым сделал логи час назад, вот что вышло: site-setup, server-scripts, drupal-scripts.

Для проектов на своем Gitlab все сложнее: чтобы правильно делались ссылки на коммиты, нужно, во-первых, указать адрес проекта через файл package.json:

А во-вторых не знаю, что надо сделать, он генерит ссылки с сокращенными хэшами, которые Github понимает, а Gitlab открывает страницу списка коммитов, т.к. ему нужен полный хэш, шаблон сходу не нашел.

Дальше искать не стал, думаю это оно самое.

Кроме лучшего результата из коробки и полной кастомизации мне в нем понравились модули:

    — готовый валидатор сообщений к коммитам — скрипт для pre-commit хука, проверяющий сообщения коммитов на соответствие стандартам, стандарты описываются в файле — автоматическое создание релизов на Github. У меня они уже создаются, но приходится вручную заходить туда и править сообщение к релизу

Выводы

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

Для себя я нашел инструмент, которым я теперь могу за 5 минут создавать историю изменений для проектов на основе коммитов.

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

UPD 08.03.2016

После этого коммиты с неправильными сообщениями перестанут проходить.

Перед релизом генерирую CHANGELOG.md:

Это допишет в лог содержимое коммитов с последнего релиза (semver тега). После этого остается поправить руками то, что не нравится, проставить версию.

После этого я генерирую документацию специфичной для проекта командой, коммит, тег, пуш:

После этого релиз. Релиз будем делать через conventional-github-releaser :

Еще не разобрался с тем, как это скрестить с выкладкой PHAR архива с Travis: для github-releaser нужно, чтобы релиза еще не было, но он создается автоматически при пуше тега на Github. После удаления релиза (превращения в Draft), github-releaser отработал, вставил данные CHANGELOG в релиз, все как надо.

Автоматическая генерация лога изменений проекта с помощью GitLab

В этой небольшой статье поговорим о том, что такое лог изменений проекта, зачем он нужен и как можно автоматизировать его генерацию с помощью GitLab.

Что такое changelog и для чего он нужен?

Лог изменений проекта (changelog) — это документ, в котором обычно содержится упорядоченный список версий проекта с датами их выхода, а также перечень всех изменений для каждой из версий.

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

Как вести лог изменений?

Как минимум, хороший лог изменений должен придерживаться следующих принципов:

Для каждой версии должен быть отдельный раздел.

Группировать изменения по категориям (Feature, Bug fix, Changed и т.п).

Самые новые версии должны располагаться в начале документа.

Иметь возможность навигации по файлу.

Файл с логом можно вести вручную, но мало какой разработчик будет с энтузиазмом это делать, а если вы поддерживаете одновременно несколько версий продукта, то это превращается в очень нудное занятие. Другим вариантом будет автоматизация этого процесса.

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

Как генерировать?

Для генерации воспользуемся функциональностью GitLab API, с его помощью будет формироваться файл ( CHANGELOG.md ) с логом изменений, основанный на заголовках коммитов. Добавляются только те коммиты, которые включают в себя определенную метку (Git trailers). GitLab использует эти метки для того, чтобы сгруппировать изменения по категориям.

Для генерации нужно выполнить POST запрос:

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

API access token — token

Имя последнего тега — 0.9.0

Имя ветки по умолчанию — main

Результатом выполнения будет новый раздел в ветке main, с подзаголовком 1.0.0 и диапазоном включенных коммитов 0.9.0..main.

Результатом выполнения будет новый раздел в ветке develop, с подзаголовком 1.0.0 и диапазоном включенных коммитов release_0.9.0..develop.

Как кастомизировать?

Для кастомизации используется конфигурационный файл в формате YAML. Файл должен располагаться в корне репозитория по пути: .gitlab/changelog_config.yml

Чтобы GitLab начал распознавать файл конфигурации, он должен быть расположен в ветке по умолчанию.

Для редактирования доступны следующие переменные:

date_format — формат даты, который будет использоваться в заголовке нового раздела лога изменений

template — формат данных, который будет использоваться для отображения каждой категории лога изменений

categories — псевдоним, который будет использоваться как имя категории, вместо тех, которые мы используем, как метки коммитов (git trailers)

Для примера, структура наших коммитов будет выглядеть так:

<Тип>(номер задачи): Заголовок

— Подробное описание (если оно требуется)

Используя стандартные настройки, сгенерированный файл будет выглядеть так:

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

В примере выше мы используем стандартный git trailer — Changelog и используемые для него значения: feature, bug, performance, которые и стали названиями категорий.

Чтобы изменить названия категорий, нужно добавить в файл конфигурации changelog_config.yml следующие строки:

Для генерации данных в категориях, используются шаблоны. Для примера выше, шаблон выглядит так:

Здесь мы в основном цикле проходим по всем категориям, отображаем название и количество записей в категории. В вложенном цикле совершаем обход всех записей и выписываем заголовок коммита и ссылку на него, если есть ссылка на МР, то добавляем её.

— используется для условий (if/else) и циклов (each). Каждое выражение, должно закрываться с помощью

<< . >> — используется для отображения данных доступных в шаблоне

Для отображения автора коммита, изменим текст шаблона, добавив в вложенный цикл строку by << author.reference >> после вывода ссылки на коммит.

После всех изменений, файл changelog_config.yml будет выглядеть следующим образом:

А сгенерированный файл CHANGELOG.md так:

Как автоматизировать?

Для начала настроить GitLab CI/CD. После того, как этот этап пройден, добавить в файл .gitlab-ci.yml новый stage (или изменить уже существующий) для обновления лога изменений. В нем мы должны получить имена веток для атрибутов from и to и после этого выполнить POST запрос для генерации файла CHANGELOG.md .

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

Теперь каждый раз при сборке релиза, будет добавляться новый раздел с версией currentVersion в файл CHANGELOG.md .

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

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

Руководство по написанию changelog

Этот документ описывает рекомендуемые правила оформления секции %changelog spec-файла пакета и характер/объём включаемой в неё информации.

Примеры [ править ]

Выпуск, включающий совместную работу:

либо более тяжеловесный вариант в случае значительных объёмов отмеченных изменений на нескольких участников выпуска:

Термины [ править ]

запись Всё, что относится к сборке 4.6.2-alt7.pre1 группа имя в квадратных скобках пункт текст, начинающийся с дефиса («- make visible_tabs and visible_tws mcedit options configurable through config file (Debian)») подпункт текст, начинающийся с плюса («+ recognize man pages with additional suffixes other than ‘x’, such as write.3p (Debian)») строка одна строка файла спека («- make visible_tabs and visible_tws mcedit options configurable through config»)

Синтаксис чейнджлога [ править ]

  • (Опциональная) группа состоит из имени в квадратных скобках и начинается с первой позиции строки.
  • Пункт верхнего уровня начинается с 1-й позиции в строке и состоит из дефиса, пробела и собственно текста.
  • Подпункт начинается с 3-й позиции в строке и состоит из плюса, пробела и собственно текста.
  • Строки переносятся по словам и содержат не более 78 символов. При этом текст новой строки выравнивается по началу текста предыдущей (то есть 3-я позиция для пунктов верхнего уровня и 5-я для подпунктов).
  • Начинать новую строку с символа # нельзя (такая строка будет воспринята как комментарий).
  • При использовании макросов следует экранировать символ «%» ещё одним «%» во избежание раскрытия оных, т.е. напрмер вместо %name следует записать %%name.

Содержимое [ править ]

  • Чейнджлог пишется на английском языке.
  • При сборке новой upstream-версии это указывается первым пунктом.
    • При сборке из снэпшота системы контроля версий необходимо указать информацию, позволяющую идентифицировать это снэпшот (дата и время для CVS, ревизия SVN, 8 первых символов идентификатора коммита для git, mtn, bzr, hg, либо вывод git-describe для git).

    Информация об уязвимостях (CVE и т.д.) в Changelog обязана соответствовать Vulnerability_Policy.

    • Изменения, произведённые апстримом (кроме исправлений ошибок безопасности), в чейнджлоге не указываются (для этого есть чейнджлоги апстрима, зачастую включаемые в пакет).
    • Косметические изменения спек-файла, не влияющие на получаемый пакет, указываются максимум одной строкой («spec cleanup»), либо не указываются вовсе. Это не относится к исправлениям тега License, изменениям параметров сборки и т. д.
    • Исправления, необходимые для успешной сборки, соответствия требованиям ALT Linux и т. д., не указываются, если они были сопряжены с упаковкой новой версии и для старой версии были не нужны (эти исправления — адаптация новой версии, то есть часть процесса её упаковки). Если же они были вызваны изменением требований либо окружения, желательно это указать (пример: «fix FTBFS with new autotools», FTBFS == failure to build from source).
    • Если .spec-файл адаптирован из другого дистрибутива, то майнтейнер вправе как оставить старые записи %changelog, так и удалить их. Следует помнить, что
      • Записи в %changelog содержат информацию о том, как шла разработка пакета до импорта — в них есть адреса майнтейнеров и протокол их действий. Эта информация часто бывает полезной.
      • Сам адаптированный спек является модификацией исходного кода, авторские права на который принадлежат не вам. Некоторые лицензии требуют сохрания атрибуции непосредственно в тексте исходного кода. Самый простой способ сделать это — оставить прошлый %changelog в неприкосновенности
      • Формат унаследованного %changelog может отличаться от принятого в ALT, это иногда приводит к сбою в инструментах работы со спеками.
      • Если вы оставляете исходный %changelog, первую запись о сборке адаптированного пакета стоит делать видимой (традиционно она содержит слова «Initial build for ALT»). Это поможет отделить историю пакета в ALT от исходной истории разработки

      Указание источников и контекста [ править ]

      • Если изменение взято извне либо основано на взятом извне, в соответствующем изменению пункте чейнджлога в скобках указывается источник. Это может быть название дистрибутива/репозитория, название внешней BTS и номер бага в ней, ID участника ALT Linux Team или произвольное указание на человека или сайт. Здесь под изменением подразумевается готовый патч, адаптированный патч или иные аналогичные указания.

      Автозакрытие багов [ править ]

      • Если изменение связано с багрепортом из bugzilla.altlinux.org, в соответствующем пункте можно указать (по вкусу; регистр не учитывается, но обязательно в скобках):
        • (Closes: NNNN)
        • (ALT NNNN)
        • (ALT bug NNNN)

        с опциональным знаком # перед номером бага. Можно также указать несколько багов: (Closes: NNNN, MMMM, ZZZZ). Синтаксис такого рода закрывает указанный баг после прохождения пакета в репозиторий при условии присутствия соответствующей записи в выводе rpmquery —lastchange .

        • Номера багов в скобках разделяются запятыми.

        Обратите внимание, что других слов в скобках при этом нельзя указывать.

        Полный regexp для поиска номеров багов в changelog можно посмотреть здесь.

Добавить комментарий

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