Инженерия

Keep a Changelog, реально внедрённый

5 мин чтения обновлено

Keep a Changelog — это конвенция на одну страницу для CHANGELOG.md: самая новая версия первая, один раздел на версию с номером и датой ISO, записи, сгруппированные под шестью типами (Added, Changed, Deprecated, Removed, Fixed, Security), и раздел Unreleased сверху для записей между релизами. Большинство команд, ссылающихся на неё, внедряют около двух третей, а треть, которую они оставляют, — это та треть, что защищает их пользователей.

Оливье Лакан опубликовал Keep a Changelog в 2014 году с фразой, которая состарилась лучше большинства прозы о софте: don’t let your friends dump git logs into changelogs. Десять лет спустя это ближайшее к стандарту, что есть в этом уголке софта. Стоит прочитать источник, а не пересказ; этот текст о частях, которые оставляют в стороне.

Что требует Keep a Changelog?

CHANGELOG.md в корне репо, самая новая версия первая, с одним разделом на версию. Каждая версия несёт номер и дату ISO, и группирует свои записи под шестью типами:

ТипДляЦена его оставления в стороне
AddedНовые функцииНичего; никто это не оставляет
ChangedИзменения в существующем поведенииЧитатели узнают об изменении поведения из ошибки
DeprecatedФункции на пути к удалениюУдаление становится инцидентом вместо запланированного события
RemovedФункции, удалённые в этом релизеНикто не отличает удаление от бага
FixedИсправления баговНичего; никто это тоже не оставляет
SecurityУязвимостиЕдинственная читательница, искавшая это, не находит

Плюс раздел Unreleased сверху, чтобы было место для записи в момент её merge, и чтобы каждый мог увидеть, что грядёт.

Это почти всё. Остальное — обоснование: записи для людей, одна запись на изменение, и файл — документ, а не лог.

Какие части Keep a Changelog оставляют в стороне?

Раздел Unreleased, затем четыре из шести типов, Security в их числе, в этом порядке.

Unreleased исчезает первым. Это раздел без дедлайна, поэтому его поддержка прекращается первой, и как только он исчезает, записи пишутся в момент релиза из истории коммитов. Это именно тот сброс git-лога, о котором спецификация предупреждает с самого начала, достигнутый постепенно. Автоматизация changelog в основном о том, как поддерживать этот раздел живым без того, чтобы кто-то должен был помнить об этом.

Шесть типов схлопываются в два. Большинство реальных changelog заканчиваются с Added и Fixed, потому что Changed и Deprecated требуют суждения о том, на что кто-то полагался. Это суждение — ценная часть. Deprecated в частности — единственный тип, являющийся обещанием о будущем, и его пропуск — это как удаление превращается в инцидент; механика соблюдения этого обещания — в как деприкейтить API.

Security перестаёт быть отдельным. Исправление безопасности, помещённое под Fixed, невидимо для единственной читательницы, искавшей его. Держите его отдельно, даже когда исправление тривиально, и особенно когда вы предпочли бы не привлекать к нему внимание.

На что не отвечает спецификация?

Это формат файла. Он ничего не говорит о вопросах, с которыми вы сталкиваетесь сразу после её принятия:

  • Как кто-то узнаёт? Файл в репо достигает контрибьюторов. Он не достигает клиентку, которая никогда не открывала GitHub.
  • А продукты без версий? Непрерывно развёртываемый сервис не имеет v4.2.0, по которой можно группировать. Большинство команд заменяют это датами, что работает, и спецификация это ни благословляет, ни запрещает.
  • Кто пишет запись? Спецификация предполагает, что это делает человек. Она не говорит когда.
  • А множество аудиторий? Один файл обслуживает разработчиков. Он не обслуживает тем же содержимым нетехническую администраторку, и ручное переформатирование для неё — то, откуда начинается дублирование. Changelog vs release notes — это разделение, которое спецификация оставляет вам сделать самостоятельно.

Common Changelog, более строгий форк идеи, ужесточает часть этого: запрещает определённые формулировки записей, требует ссылку на изменение, и имеет чёткое мнение о том, кто читатель. Стоит прочитать, если свободные части Keep a Changelog — это то, о чём ваша команда постоянно спорит.

Можно ли автоматизировать Keep a Changelog без сброса git-логов?

Да: выводите черновик из структурированных коммитов, помещайте его в Unreleased с предзаполненным типом, и требуйте, чтобы человек редактировал формулировку перед выпуском релиза. Предупреждение спецификации о результате, а не об инструменте. Выведение черновика из коммитов — это нормально. Публикация этого черновика без редактирования — то, против чего она возражает.

Машина занимается сбором и форматированием, в чём она хороша. Человек занимается отбором и формулировкой, в чём она не хороша. Conventional commits описывают то разделение на два уровня, на которое это опирается, и то, какие типы коммитов соответствуют каким из шести категорий выше. Наш обзор инструменты для changelog охватывает, что существует для половины сбора.

Где Keep a Changelog перестаёт быть достаточным?

Он останавливается на распространении. Keep a Changelog — хороший ответ на «как должен выглядеть этот файл». Это не ответ на «как наши пользователи узнают, что изменилось», потому что файл Markdown в репо — это стратегия распространения, работающая только если ваши пользователи — контрибьюторы.

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

Всё равно примите спецификацию. Она стоит вечера, делает вторую проблему решаемой, и всё ещё лучшая страница, когда-либо написанная об этом.

FAQ

Является ли Keep a Changelog стандартом? Это широко принятая конвенция, а не спецификация органа стандартизации. Инструменты (скрипты релиза, линтеры, парсеры) достаточно часто предполагают её форму, чтобы её следование покупало совместимость.

Что попадает в раздел Unreleased? Каждая запись для изменения, которое было объединено, но ещё не выпущено в пронумерованном релизе. Когда релиз выпускается, раздел переименовывается в версию и дату, а новый, пустой раздел Unreleased идёт над ним.

Должен ли changelog использовать семантическое версионирование? Keep a Changelog рекомендует это и не требует. Библиотеки и API от этого выигрывают; непрерывно развёртываемый сервис обычно заменяет это датами, что формат допускает.

Должны ли исправления безопасности быть в changelog до того, как они публичны? Добавьте запись, когда исправление выпущено, с достаточной детализацией, чтобы оператор мог действовать, и не более. Отложить запись до даты скоординированного раскрытия нормально; опустить её — нет.


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

По теме на changeloop: Примеры changelog, Сравнение инструментов changelog

changeloop
Команда, которая делает changelog, замыкающий цикл. Пользователи о чём-то просят, ваша команда это делает, тот, кто просил, узнаёт об этом.